Jika Anda mencari batasan yang baik pada kesalahan pembulatan Anda, Anda tidak perlu pustaka presisi aribtrary. Anda dapat menggunakan analisis kesalahan yang sedang berjalan.
Saya tidak dapat menemukan referensi online yang bagus, tetapi semuanya dijelaskan dalam Bagian 3.3 buku Nick Higham "Akurasi dan Stabilitas Algoritma Numerik". Idenya cukup sederhana:
- Re-faktor kode Anda sehingga Anda memiliki satu tugas operasi aritmatika tunggal di setiap baris.
- Untuk setiap variabel, misalnya
x
, buat variabel x_err
yang diinisialisasi ke nol ketika x
diberi konstanta.
- Untuk setiap operasi, misalnya
z = x * y
, memperbarui variabel z_err
menggunakan model standar aritmatika floating-point dan yang dihasilkan z
kesalahan dan berjalan x_err
dan y_err
.
- Nilai kembalinya fungsi Anda juga harus memiliki
_err
nilai terkait. Ini adalah ketergantungan data yang terikat pada kesalahan pembulatan total Anda.
Bagian yang sulit adalah langkah 3. Untuk operasi aritmatika yang paling sederhana, Anda dapat menggunakan aturan berikut:
z = x + y
-> z_err = u*abs(z) + x_err + y_err
z = x - y
-> z_err = u*abs(z) + x_err + y_err
z = x * y
-> z_err = u*abs(z) + x_err*abs(y) + y_err*abs(x)
z = x / y
-> z_err = u*abs(z) + (x_err*abs(y) + y_err*abs(x))/y^2
z = sqrt(x)
-> z_err = u*abs(z) + x_err/(2*abs(z))
di mana u = eps/2
unit pembulatan. Ya, aturan untuk +
dan -
sama. Aturan untuk operasi lain op(x)
dapat dengan mudah diekstraksi menggunakan ekspansi seri Taylor dari hasil yang diterapkan op(x + x_err)
. Atau Anda dapat mencoba googling. Atau menggunakan buku Nick Higham.
Sebagai contoh, pertimbangkan kode Matlab / Oktaf berikut yang mengevaluasi polinomial dalam koefisien a
pada suatu titik x
menggunakan skema Horner:
function s = horner ( a , x )
s = a(end);
for k=length(a)-1:-1:1
s = a(k) + x*s;
end
Untuk langkah pertama, kami membagi dua operasi di s = a(k) + x*s
:
function s = horner ( a , x )
s = a(end);
for k=length(a)-1:-1:1
z = x*s;
s = a(k) + z;
end
Kami kemudian memperkenalkan _err
variabel. Perhatikan bahwa input a
dan x
dianggap tepat, tetapi kita juga bisa meminta pengguna untuk memberikan nilai yang sesuai untuk a_err
dan x_err
:
function [ s , s_err ] = horner ( a , x )
s = a(end);
s_err = 0;
for k=length(a)-1:-1:1
z = x*s;
z_err = ...;
s = a(k) + z;
s_err = ...;
end
Akhirnya, kami menerapkan aturan yang dijelaskan di atas untuk mendapatkan persyaratan kesalahan:
function [ s , s_err ] = horner ( a , x )
u = eps/2;
s = a(end);
s_err = 0;
for k=length(a)-1:-1:1
z = x*s;
z_err = u*abs(z) + s_err*abs(x);
s = a(k) + z;
s_err = u*abs(s) + z_err;
end
Perhatikan bahwa karena kita tidak memiliki a_err
atau x_err
, misalnya mereka dianggap nol, istilah masing-masing hanya diabaikan dalam ekspresi kesalahan.
Dan lagi! Kami sekarang memiliki skema Horner yang mengembalikan perkiraan kesalahan yang bergantung pada data (catatan: ini adalah batas atas kesalahan) di samping hasilnya.
Sebagai catatan, karena Anda menggunakan C ++, Anda dapat mempertimbangkan membuat kelas Anda sendiri untuk nilai-nilai floating-point yang membawa sekitar _err
istilah dan membebani semua operasi aritmatika untuk memperbarui nilai-nilai ini seperti yang dijelaskan di atas. Untuk kode besar, ini mungkin rute yang lebih mudah, meskipun secara komputasi kurang efisien. Karena itu, Anda mungkin dapat menemukan kelas online semacam itu. Pencarian Google cepat memberi saya tautan ini .
PS Perhatikan bahwa ini semua hanya bekerja pada mesin yang hanya mematuhi IEEE-754, yaitu semua operasi aritmatika tepat untuk . Analisis ini juga memberikan ikatan yang lebih ketat dan lebih realistis daripada menggunakan aritmatika interval karena, menurut definisi, Anda tidak dapat mewakili angka di titik mengambang, yaitu interval Anda hanya akan membulatkan ke angka itu sendiri.± ux ( 1 ± u )