Rumah > Soal Jawab > teks badan
Pertimbangkan kod berikut:
0.1 + 0.2 == 0.3 -> false
0.1 + 0.2 -> 0.30000000000000004
Mengapa ketidaktepatan ini berlaku?
P粉5205457532023-10-12 10:27:06
Saya percaya saya harus menambah perspektif pereka perkakasan, kerana saya mereka bentuk dan membina perkakasan titik terapung. Mengetahui punca ralat boleh membantu memahami perkara yang berlaku dalam perisian, dan akhirnya, saya harap ini membantu menjelaskan sebab ralat titik terapung berlaku dan nampaknya terkumpul dari semasa ke semasa.
Dari perspektif kejuruteraan, kebanyakan operasi titik terapung akan mengalami sedikit ralat kerana perkakasan yang melakukan pengiraan titik terapung hanya perlu mempunyai ralat kurang daripada setengah unit dalam bit terakhir. Oleh itu, banyak perkakasan akan berhenti pada ketepatan yang hanya memerlukan ralat kurang daripada satu unit pada bit terakhir operasi tunggal , yang amat bermasalah dalam pembahagian titik terapung. Apa yang membentuk satu operasi bergantung pada berapa banyak operan yang diperlukan untuk unit itu. Bagi kebanyakan, ia adalah dua, tetapi sesetengah unit memerlukan 3 atau lebih operan. Oleh itu, tiada jaminan bahawa operasi berulang akan menghasilkan ralat yang diingini, kerana ralat terkumpul dari semasa ke semasa.
2. Standard3. Punca kesilapan pembahagian dan pembundaran
bit (ditambah beberapa bit pilihan). Z=X/Y
、Z = X * (1/Y)
。除法是迭代计算的,即每个周期计算商的一些位,直到达到所需的精度,对于 IEEE-754 来说,精度是最后一位误差小于一个单位的任何值。 Y(1/Y)的倒数表在慢除法中被称为商选择表(QST),商选择表的大小(以位为单位)通常是基数的宽度,或者是基数的位数。每次迭代中计算的商,加上一些保护位。对于 IEEE-754 标准,双精度(64 位),它是除法器基数的大小,加上一些保护位 k,其中 k>=2
。例如,一次计算 2 位商(基数 4)的除法器的典型商选择表将是 2+2= 4
3.1 Ralat pembundaran bahagian: penghampiran timbal balik
Timbal balik dalam jadual pemilihan quotient bergantung pada divisyen: bahagian perlahan seperti bahagian SRT, atau bahagian pantas seperti bahagian Goldschmidt setiap entri diubah suai mengikut algoritma bahagian untuk cuba menghasilkan ralat yang paling rendah. Walau apa pun, semua salingan adalah anggaran salingan sebenar dan akan memperkenalkan beberapa unsur ralat. Kedua-dua pembahagian perlahan dan pembahagian pantas mengira hasil bahagi secara berulang, iaitu setiap langkah mengira bilangan digit dalam hasil bahagi dan kemudian menolak hasil daripada dividen Pembahagi mengulangi langkah ini sehingga ralat kurang daripada setengah unit di tempat terakhir . Kaedah pembahagian perlahan mengira hasil bagi bilangan digit yang tetap dalam setiap langkah dan secara amnya lebih murah untuk dibina, manakala kaedah pembahagian pantas mengira bilangan digit yang berubah-ubah dalam setiap langkah dan secara amnya lebih mahal untuk dibina. Bahagian yang paling penting tentang pembahagian ialah kebanyakannya bergantung pada pendaraban berulang bagi hampiran timbal balik, jadi mudah untuk membuat kesilapan.
Sebab lain untuk ralat pembundaran dalam semua operasi ialah mod pemangkasan berbeza bagi jawapan akhir yang dibenarkan oleh IEEE-754. Terdapat potong, bulat ke arah sifar, bulat ke terdekat (lalai), bulat ke bawah, bundarkan ke atas. Untuk satu operasi, semua kaedah memperkenalkan elemen ralat kurang daripada satu unit pada penghujungnya. Pemangkasan juga secara kumulatif meningkatkan ralat akhir dari semasa ke semasa dan dengan operasi berulang. Ralat pemangkasan ini amat bermasalah apabila pengeksponenan melibatkan beberapa bentuk pendaraban berulang.
Oleh kerana perkakasan yang melakukan pengiraan titik terapung hanya perlu menghasilkan keputusan dengan ralat kurang daripada separuh dalam bit terakhir dalam satu operasi, jika anda tidak berhati-hati, ralat akan meningkat dengan operasi berulang. Inilah sebabnya mengapa dalam pengiraan yang memerlukan ralat terhad, ahli matematik menggunakan kaedah seperti membundarkan kepada Aritmetik Selang digabungkan dengan varian Mod Pembundaran IEEE 754 untuk meramalkan ralat pembundaran dan membetulkannya. Membundarkan kepada digit genap terdekat (digit terakhir) ialah mod pembundaran lalai untuk IEEE-754 disebabkan oleh ralat relatif yang lebih rendah berbanding dengan mod pembundaran lain.
Sila ambil perhatian bahawa mod pembundaran lalai membundarkan kepada nombor genap a> terdekat bagi digit terakhir, memastikan ralat digit terakhir dalam satu operasi adalah kurang daripada separuh. Pemotongan, pembundaran ke atas dan pembundaran ke bawah sahaja boleh mengakibatkan ralat lebih besar daripada separuh daripada digit terakhir tetapi kurang daripada satu unit digit terakhir, jadi mod ini tidak disyorkan kecuali untuk aritmetik selang.
Ringkasnya, punca ralat dalam operasi floating point adalah gabungan pemangkasan perkakasan dan pemangkasan timbal balik semasa pembahagian. Oleh kerana piawaian IEEE-754 hanya memerlukan ralat dalam bit terakhir operasi tunggal kurang daripada separuh, ralat titik terapung daripada operasi berulang akan terkumpul melainkan diperbetulkan.
P粉5634465792023-10-12 10:02:37
Binary Floating pointMath macam ni. Dalam kebanyakan bahasa pengaturcaraan, ia berdasarkan standard IEEE 754. Inti dari perkara ini ialah nombor diwakili dalam format ini sebagai integer yang didarab dengan kuasa 2 yang penyebutnya bukan kuasa 2 (seperti 0.1
,即1/10
) tidak boleh diwakili dengan tepat.
Untuk standard binary64
格式的 0.1
, representasinya boleh ditulis betul-betul seperti
0.10000000000000000055511151231257827021181583404541015625
(perpuluhan), atau 0x1.999999999999ap-4
Perwakilan titik terapung heksadesimal C99< /a>.Sebaliknya, nombor rasional0.1
,即1/10
, boleh ditulis tepat seperti
0.1
(perpuluhan), atau 0x1.99999999999999...p-4
类似于 C99 十六进制浮点表示法,其中 ...
bermaksud urutan 9s yang tidak berkesudahan. Pemalar 0.2
dan 0.3
dalam program juga akan menjadi anggaran nilai sebenar mereka. Seperti yang berlaku, double
yang paling hampir dengan 0.2
adalah lebih besar daripada nombor rasional 0.2
, tetapi yang paling hampir dengan double
kod>0.3 Kurang daripada nombor rasional 0.3
. Jumlah 0.2
和0.3
也将是其真实值的近似值。碰巧,最接近 0.2
的 double
大于有理数 0.2
,但最接近 double
code>0.3 小于有理数 0.3
。 0.1
和 0.2
的总和最终大于有理数 0.3
dan 0.2
akhirnya menjadi lebih besar daripada nombor rasional 0.3
dan oleh itu tidak konsisten dengan pemalar dalam kod.
Rawatan yang agak menyeluruh bagi masalah aritmetik titik terapung ialah Setiap saintis komputer harus tahu tentang aritmetik titik terapung. Untuk penjelasan yang lebih mudah difahami, lihat floating-point-gui.de.
Nombor perpuluhan lama biasa (asas 10) mempunyai masalah yang sama, sebab itu nombor seperti 1/3 akhirnya menjadi 0.333333333...
Anda baru sahaja terjumpa nombor (3/10) yang mudah diwakili dalam perpuluhan, tetapi tidak dalam sistem binari. Ia juga berjalan kedua-dua arah (pada tahap tertentu): 1/16 ialah nombor yang jelek dalam perpuluhan (0.0625), tetapi dalam perduaan ia kelihatan seperti perpuluhan ke-10,000 (0.0001)** - jika kita sudah tiba masanya. tabiat menggunakan sistem nombor asas 2 dalam kehidupan seharian kita, malah anda akan melihat nombor itu dan secara naluriah memahami bahawa anda boleh mencapai nombor itu dengan mengurangkan separuh sesuatu, dan mengurangkan separuh lagi, dan lagi dan lagi.
Sudah tentu, ini bukan cara nombor terapung disimpan dalam ingatan (ia menggunakan tatatanda saintifik). Walau bagaimanapun, ia menggambarkan bahawa ralat ketepatan titik terapung binari cenderung timbul kerana nombor "dunia nyata" yang biasanya kita minati biasanya adalah kuasa sepuluh - tetapi itu hanya kerana kita menggunakan sistem penomboran perpuluhan hari ini - hari ini. Itulah sebabnya kami menyebut 71% dan bukannya "5 daripada setiap 7" (71% ialah anggaran kerana 5/7 tidak boleh diwakili dengan tepat oleh sebarang nombor perpuluhan).
Jadi tidak: nombor titik terapung binari tidak rosak, ia kebetulan tidak sempurna seperti sistem nombor berasaskan N yang lain :)
Dalam amalan, isu ketepatan ini bermakna anda perlu menggunakan fungsi pembundaran untuk membundarkan nombor titik terapung kepada bilangan tempat perpuluhan yang anda minati sebelum memaparkannya.
Anda juga perlu menggantikan ujian kesaksamaan dengan perbandingan yang membolehkan tahap toleransi tertentu, yang bermaksud:
Jangan jangan buat if (x == y) { ... }
Sebaliknya laksanakan if (abs(x - y) < myToleranceValue) { ... }
.
Yang manakah abs
是绝对值。 myToleranceValue
perlu dipilih berdasarkan aplikasi khusus anda - ia mempunyai banyak kaitan dengan "bilik goyang" yang anda sediakan untuk membenarkan, dan kemungkinan jumlah terbesar yang anda bandingkan (disebabkan oleh isu kehilangan ketepatan) . Perhatikan pemalar gaya "epsilon" dalam bahasa pilihan anda. Ini boleh digunakan sebagai nilai toleransi, tetapi keberkesanannya bergantung pada saiz (saiz) nombor yang anda gunakan, kerana pengiraan pada nombor besar mungkin melebihi ambang epsilon.