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_erryang diinisialisasi ke nol ketika xdiberi konstanta.
- Untuk setiap operasi, misalnya
z = x * y, memperbarui variabel z_errmenggunakan model standar aritmatika floating-point dan yang dihasilkan zkesalahan dan berjalan x_errdan y_err.
- Nilai kembalinya fungsi Anda juga harus memiliki
_errnilai 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/2unit 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 apada suatu titik xmenggunakan 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 _errvariabel. Perhatikan bahwa input adan xdianggap tepat, tetapi kita juga bisa meminta pengguna untuk memberikan nilai yang sesuai untuk a_errdan 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_erratau 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 _erristilah 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 )