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 )
Sebuah pustaka portabel dan sumber terbuka yang bagus untuk aritmatika floating point presisi sewenang-wenang (dan banyak lagi lainnya) adalah NTL Victor Shoup , yang tersedia dalam bentuk sumber C ++.
Pada tingkat yang lebih rendah adalah Bignum Library GNU Multiple Precision (GMP) , juga merupakan paket sumber terbuka.
NTL dapat digunakan dengan GMP jika diperlukan kinerja yang lebih cepat, tetapi NTL menyediakan rutinitas basisnya sendiri yang tentu dapat digunakan jika Anda "tidak peduli dengan kecepatan". GMP mengklaim sebagai "perpustakaan bignum tercepat". GMP sebagian besar ditulis dalam bahasa C, tetapi memiliki antarmuka C ++.
Ditambahkan: Sementara interval aritmatika dapat memberikan batas atas dan bawah pada jawaban yang tepat dengan cara otomatis, ini tidak secara akurat mengukur kesalahan dalam perhitungan presisi "standar" karena ukuran interval biasanya tumbuh dengan setiap operasi (baik dalam relatif atau pengertian kesalahan absolut).
Cara khas untuk menemukan ukuran kesalahan, baik untuk kesalahan pembulatan atau untuk kesalahan diskritisasi, dll., Adalah untuk menghitung nilai presisi ekstra dan membandingkannya dengan nilai presisi "standar". Hanya presisi ekstra sederhana yang diperlukan untuk menentukan ukuran kesalahan itu sendiri untuk akurasi yang masuk akal, karena kesalahan pembulatan saja secara substansial lebih besar dalam presisi "standar" daripada mereka dalam perhitungan presisi ekstra.
Intinya dapat diilustrasikan dengan membandingkan perhitungan presisi tunggal dan ganda. Perhatikan bahwa dalam ekspresi menengah C ++ selalu dihitung dalam (setidaknya) presisi ganda, jadi jika kita ingin menggambarkan seperti apa komputasi dalam presisi tunggal "murni" itu, kita perlu menyimpan nilai-nilai perantara dalam presisi tunggal.
Cuplikan kode C
Output dari atas (rantai alat Cygwin / MinGW32 GCC):
Jadi kesalahannya adalah tentang apa yang diharapkan dalam pembulatan 1/3 ke presisi tunggal. Seseorang tidak akan (saya curiga) peduli untuk mendapatkan lebih dari beberapa tempat desimal dalam kesalahan yang benar, karena pengukuran kesalahan adalah untuk besarnya dan bukan untuk ketepatan.
sumber
GMP (yaitu, GNU Multiple Precision library) adalah perpustakaan presisi arbitrer terbaik yang saya tahu.
Saya tidak tahu cara terprogram untuk mengukur kesalahan dalam hasil fungsi floating point arbitrer. Satu hal yang bisa Anda coba adalah menghitung perpanjangan interval dari suatu fungsi menggunakan interval aritmatika . Di C ++, Anda harus menggunakan semacam perpustakaan untuk menghitung ekstensi interval; salah satu perpustakaan tersebut adalah Boost Interval Arithmetic Library. Pada dasarnya, untuk mengukur kesalahan, Anda akan menyediakan sebagai argumen untuk interval fungsi Anda yang memiliki lebar 2 kali pembulatan unit (kira-kira), berpusat pada nilai-nilai yang menarik, dan kemudian output Anda akan menjadi kumpulan interval, lebar yang akan memberi Anda beberapa perkiraan kesalahan yang konservatif. Kesulitan dengan pendekatan ini adalah bahwa aritmatika interval yang digunakan dalam mode ini dapat melebih-lebihkan kesalahan dengan jumlah yang signifikan, tetapi pendekatan ini adalah yang paling "terprogram" yang bisa saya pikirkan.
sumber
Estimasi kesalahan yang ketat dan otomatis dapat dicapai dengan analisis interval . Anda bekerja dengan interval alih-alih angka. Misalnya penambahan:
Pembulatan juga dapat ditangani dengan ketat, lihat Rounded interval aritmatika .
Selama input Anda terdiri dari interval yang sempit, estimasi tersebut OK dan setiap hari murah untuk dihitung. Sayangnya, kesalahan sering ditaksir berlebihan, lihat masalah ketergantungan .
Saya tidak tahu ada perpustakaan aritmatika interval presisi sewenang-wenang.
Tergantung pada masalah Anda, apakah interval aritmatika dapat memenuhi kebutuhan Anda atau tidak.
sumber
The GNU MPFR perpustakaan adalah mengambang perpustakaan sewenang-wenang-presisi yang memiliki akurasi tinggi (khususnya, pembulatan benar untuk semua operasi, yang tidak semudah kedengarannya) sebagai salah satu titik fokus utama mereka. Ini menggunakan GNU MP di bawah tenda. Ini memiliki ekstensi yang disebut MPFI yang melakukan aritmatika interval, yang - seperti jawaban Geoff - mungkin berguna untuk keperluan verifikasi: terus meningkatkan presisi kerja sampai interval yang dihasilkan jatuh dalam batas kecil.
Ini tidak akan selalu berhasil; khususnya itu belum tentu efektif jika Anda melakukan sesuatu seperti integrasi numerik, di mana setiap langkah membawa "kesalahan" terlepas dari masalah pembulatan. Dalam hal itu, coba paket khusus seperti COZY infinity yang melakukan ini dengan sangat baik menggunakan algoritma spesifik untuk mengikat kesalahan integrasi (dan menggunakan apa yang disebut model Taylor alih-alih interval).
sumber
Saya diberitahu bahwa MPIR adalah perpustakaan yang baik untuk digunakan jika Anda bekerja dengan Visual Studio:
http://mpir.org/
sumber