Saya menyadari bahwa aritmatika floating point memiliki masalah presisi. Saya biasanya mengatasinya dengan beralih ke representasi angka desimal tetap, atau hanya dengan mengabaikan kesalahan.
Namun, saya tidak tahu apa penyebab ketidaktepatan ini. Mengapa ada begitu banyak masalah pembulatan dengan angka float?
decimal
tipe .NET bekerja. Titik tetap, di sisi lain, berbeda. Selama rentang Anda terbatas, titik tetap adalah jawaban yang baik. Tetapi rentang terbatas membuat titik tetap tidak cocok untuk banyak aplikasi matematika, dan implementasi angka titik tetap sering tidak dioptimalkan dengan baik dalam perangkat keras sebagai hasilnya.Jawaban:
Ini karena beberapa fraksi membutuhkan jumlah tempat yang sangat besar (atau bahkan tak terbatas) untuk diekspresikan tanpa pembulatan. Ini berlaku untuk notasi desimal sebanyak untuk biner atau lainnya. Jika Anda membatasi jumlah tempat desimal yang akan digunakan untuk perhitungan Anda (dan menghindari membuat perhitungan dalam notasi pecahan), Anda harus membulatkan bahkan ekspresi sederhana seperti 1/3 + 1/3. Alih-alih menulis 2/3 sebagai hasilnya Anda harus menulis 0,33333 + 0,33333 = 0,66666 yang tidak identik dengan 2/3.
Dalam hal komputer jumlah digit dibatasi oleh sifat teknis dari register memori dan CPU-nya. Notasi biner yang digunakan secara internal menambah beberapa kesulitan. Komputer biasanya tidak dapat mengekspresikan angka dalam notasi pecahan, meskipun beberapa bahasa pemrograman menambahkan kemampuan ini, yang memungkinkan masalah-masalah tersebut dihindari pada tingkat tertentu.
Apa Yang Harus Diketahui Setiap Ilmuwan Komputer Tentang Aritmatika Titik Apung
sumber
Terutama, kesalahan pembulatan berasal dari fakta bahwa tak terhingga dari semua bilangan real tidak mungkin diwakili oleh memori terbatas komputer , apalagi sepotong kecil memori seperti variabel floating point tunggal , begitu banyak angka yang disimpan hanyalah perkiraan dari jumlah yang harus mereka wakili.
Karena hanya ada sejumlah nilai yang bukan perkiraan, dan operasi apa pun antara perkiraan dan angka lainnya menghasilkan perkiraan, kesalahan pembulatan hampir tidak bisa dihindari .
Yang penting adalah untuk menyadari ketika mereka cenderung menyebabkan masalah dan mengambil langkah-langkah untuk mengurangi risiko .
Selain David Goldberg , Apa Yang Harus Diketahui Setiap Ilmuwan Komputer Tentang Aritmatika Titik Apung (diterbitkan ulang oleh Sun / Oracle sebagai lampiran dari Panduan Perhitungan Numerik mereka ), yang disebutkan oleh thorsten , jurnal ACCU yang kelebihan beban sangat bagus serangkaian artikel oleh Richard Harris tentang Floating Point Blues .
Seri dimulai dengan
Richard mulai dengan menjelaskan taksonomi bilangan real, rasional, irasional, aljabar, dan transendental. Dia kemudian menjelaskan representasi IEEE754, sebelum melanjutkan ke kesalahan pembatalan dan urutan masalah eksekusi.
Jika Anda membaca tidak lebih dalam dari ini, Anda akan memiliki landasan yang sangat baik dalam masalah yang terkait dengan angka floating point.
Namun jika Anda ingin tahu lebih banyak, ia melanjutkan
Dia kemudian beralih untuk mencoba membantu Anda menyembuhkan Blues Kalkulus Anda
dan terakhir namun tidak kalah pentingnya, ada
Seluruh seri artikel layak untuk dilihat, dan total 66 halaman, mereka masih lebih kecil dari 77 halaman dari makalah Goldberg .
Sementara seri ini mencakup banyak hal yang sama, saya menemukan itu lebih mudah diakses daripada kertas Goldberg . Saya juga merasa lebih mudah untuk memahami bagian-bagian yang lebih kompleks dari kertas setelah membaca artikel Richards sebelumnya dan setelah artikel-artikel awal, Richard bercabang ke banyak bidang menarik yang tidak disentuh oleh kertas Goldberg.
Seperti yang dikatakan oleh ak dalam komentar:
sumber
Nah, thorsten memiliki tautan pasti . Saya akan menambahkan:
Setiap bentuk representasi akan memiliki beberapa kesalahan pembulatan untuk beberapa nomor. Cobalah untuk mengekspresikan 1/3 dalam floating point IEEE, atau dalam desimal. Tidak ada yang bisa melakukannya dengan akurat. Ini melampaui menjawab pertanyaan Anda, tetapi saya telah menggunakan aturan praktis ini dengan sukses:
sumber
Apa yang tampaknya belum disebutkan sejauh ini adalah konsep dari algoritma yang tidak stabil dan masalah yang dikondisikan . Saya akan membahas yang pertama, karena tampaknya menjadi perangkap yang lebih sering untuk numeric pemula.
Pertimbangkan perhitungan kekuatan rasio emas (timbal balik)
φ=0.61803…
; salah satu cara yang mungkin dilakukan adalah dengan menggunakan rumus rekursiφ^n=φ^(n-2)-φ^(n-1)
, dimulai denganφ^0=1
danφ^1=φ
. Jika Anda menjalankan rekursi ini di lingkungan komputasi favorit Anda dan membandingkan hasilnya dengan kekuatan yang dievaluasi secara akurat, Anda akan menemukan erosi lambat dari angka-angka penting. Inilah yang terjadi misalnya di Mathematica :Hasil yang diklaim
φ^41
memiliki tanda yang salah, dan bahkan lebih awal, nilai yang dihitung dan aktual untukφ^39
saham tidak memiliki digit yang sama (3.484899258054952
* ^ - 9for the computed version against the true value
7.071019424062048*^-9
). Algoritma demikian tidak stabil, dan orang tidak boleh menggunakan rumus rekursi ini dalam aritmatika yang tidak tepat. Hal ini disebabkan oleh sifat inheren formula rekursi: ada solusi "peluruhan" dan "tumbuh" untuk rekursi ini, dan mencoba menghitung solusi "peluruhan" dengan solusi maju ketika ada alternatif "tumbuh" solusi yang meminta. untuk kesedihan numerik. Dengan demikian seseorang harus memastikan bahwa algoritma numeriknya stabil.Sekarang, ke konsep masalah yang tidak terkondisikan : meskipun mungkin ada cara yang stabil untuk melakukan sesuatu secara numerik, mungkin saja masalah yang Anda miliki tidak dapat diselesaikan dengan algoritma Anda. Ini adalah kesalahan dari masalah itu sendiri, dan bukan metode solusinya. Contoh kanonik dalam angka adalah solusi persamaan linear yang melibatkan apa yang disebut "matriks Hilbert":
Matriks adalah contoh kanonik dari matriks yang tidak terkondisikan : mencoba memecahkan suatu sistem dengan matriks Hilbert yang besar mungkin menghasilkan solusi yang tidak akurat.
Berikut ini adalah demonstrasi Mathematica : bandingkan hasil aritmatika yang tepat
dan aritmatika yang tidak tepat
(Jika Anda mencobanya di Mathematica , Anda akan mencatat beberapa pesan kesalahan yang mengingatkan akan kondisi buruk yang muncul.)
Dalam kedua kasus, hanya meningkatkan presisi bukanlah obat; itu hanya akan menunda erosi angka yang tak terelakkan.
Inilah yang mungkin Anda hadapi. Solusinya mungkin sulit: untuk yang pertama, Anda kembali ke papan gambar, atau membaca jurnal / buku / apa pun untuk menemukan jika orang lain telah menemukan solusi yang lebih baik daripada yang Anda miliki; untuk yang kedua, Anda menyerah, atau merumuskan kembali masalah Anda menjadi sesuatu yang lebih bisa ditelusuri.
Saya akan meninggalkan Anda dengan penawaran dari Dianne O'Leary:
sumber
karena basis 10 angka desimal tidak dapat dinyatakan dalam basis 2
atau dengan kata lain 1/10 tidak dapat diubah menjadi pecahan dengan kekuatan 2 dalam penyebutnya (yang pada dasarnya adalah angka-angka floating point)
sumber
9*3.3333333
dalam desimal dan buat itu untuk9*3 1/3
.1 + .1 != .2
karena floating-point binary encoding digunakan, bukan desimal.1.0/3.0*3.0 != 1.0
, karena pengkodean biner floating-point digunakan, bukan trinary.Dalam matematika, ada banyak sekali bilangan rasional. Variabel 32 bit hanya dapat memiliki 2 32 nilai yang berbeda, dan variabel 64 bit hanya 2 64 nilai. Karena itu, ada banyak bilangan rasional yang tidak memiliki representasi yang tepat.
Kita bisa membuat skema yang memungkinkan kita untuk mewakili 1/3 dengan sempurna, atau 1/100. Ternyata untuk banyak tujuan praktis ini tidak terlalu berguna. Ada satu pengecualian besar: di bidang keuangan, pecahan desimal sering muncul. Itu terutama karena keuangan pada dasarnya adalah aktivitas manusia, bukan aktivitas fisik.
Oleh karena itu, kami biasanya memilih untuk menggunakan binary floating point, dan membulatkan nilai apa pun yang tidak dapat direpresentasikan dalam biner. Namun dalam keuangan, kami terkadang memilih floating point desimal, dan membulatkan nilai ke nilai desimal terdekat.
sumber
"√2"
. (Kalkulator HP-48 lama saya dapat melakukan hal itu, dan mengkuadratkan nilai tersebut menghasilkan tepat2.0
.) Hanya ada tak terhingga jumlah bilangan real yang dapat diwakili untuk setiap representasi terbatas - tetapi tidak ada perhitungan yang dapat menghasilkan angka yang tidak, pada prinsipnya representable. Dalam praktiknya, titik-mengambang biner secara drastis membatasi rangkaian angka yang dapat diwakili, dengan manfaat kecepatan sangat tinggi dan penyimpanan yang relatif kecil dibandingkan dengan representasi simbolik.satu-satunya "masalah pembulatan" yang benar-benar jelas dengan angka floating-point yang saya pikirkan adalah dengan filter rata-rata bergerak:
$$ \ begin {align} y [n] & = \ frac {1} {N} \ jumlah \ limit_ {i = 0} ^ {N-1} x [ni] \ & = y [n-1] + \ frac {1} {N} (x [n] - x [nN]) \ \ end {align} $$
untuk membuat ini bekerja tanpa penumpukan kebisingan, Anda ingin memastikan bahwa $ x [n] $ yang Anda tambahkan dalam sampel saat ini persis sama dengan $ x [nN] $ Anda akan mengurangi $ N $ sampel ke dalam masa depan. jika tidak, maka yang berbeda adalah kotoran kecil yang terjebak di garis penundaan Anda dan tidak akan pernah keluar. itu karena filter rata-rata bergerak ini sebenarnya dibangun dengan IIR yang memiliki kutub yang sedikit stabil pada $ z = 1 $ dan nol yang membatalkannya di dalam. tetapi, ini adalah integrator dan semua omong kosong yang terintegrasi dan tidak sepenuhnya dihapus akan ada dalam jumlah integrator selamanya. di sinilah titik tetap tidak memiliki masalah yang sama dengan angka titik apung.
sumber