程式設計技巧 浮點數操作的精度問題

2021-09-25 06:39:20 字數 1628 閱讀 5835

在大多數程式語言中,數字按照 ieee 754 的標準,使用 64 位雙精度浮點型來表示。其中符號位 s,指數字 e,尾數字m分別佔了 1,11,52 位,並且在 es5 規範 中指出了指數字e的取值範圍是 [-1074, 971]。

精度問題彙總

想用有限的位來表示無窮的數字,顯然是不可能的,因此會出現一系列精度問題

浮點數精度問題,比如

0.1 + 0.2 !== 0.3

大數精度問題,比如

9999 9999 9999 9999 == 1000 0000 0000 0000 1

四捨五入結果不準確,比如

1.335.tofixed(2) == 1.33

浮點數精度和 四捨五入其實屬於同一類問題,都是由於浮點數無法精確表示引起的,如下:

(1.335).toprecision(20); // 「1.3349999999999999645」

產生浮點數計算精度不準確的原因: 在計算機角度,計算機算的是二進位制,而不是十進位制。二進位制小數點後面變成了無限不迴圈的數,而計算機可支援浮點數的小數部分可支援到52位,所有兩者相加,在轉換成十進位制,得到的數就不準確了,加減乘除運算原理一樣。

通過以上可以明白,[min_safe_integer, max_safe_integer]的整數都可以精確表示,但是超出這個範圍的整數就不一定能精確表示。這樣就會產生所謂的大數精度丟失問題。

首先考慮的是如何解決浮點數運算的精度問題,有3種思路:

先來看第一種方案,在大多數情況下,它可以得到正確結果,但是對一些極端情況,tofixed 到 12 是不夠的,比如:

210000 * 10000 * 1000 * 8.2 // 17219999999999.998

parsefloat(17219999999999.998.tofixed(12)); // 17219999999999.998,而正確結果為 17220000000000

上面的情況,如果想讓結果正確,需要 tofixed(2),這顯然是不可接受的。

再看第二種方案,比如 number-precision 這個庫就是使用的這種方案,但是這也是有問題的,比如:

// 這兩個浮點數,轉化為整數之後,相乘的結果已經超過了 max_safe_integer

123456.789 * 123456.789 // 轉化為 (123456789 * 123456789)/1000000,結果是 15241578750.19052

所以,最終考慮使用第三種方案,目前已經有了很多較為成熟的庫,比如

bignumber.js,decimal.js,以及big.js等。

我們可以根據自己的需求來選擇對應的工具。並且,這些庫不僅解決了浮點數的運算精度問題,還支援了大數運算,並且修復了原生tofixed結果不準確的問題。

浮點數精度問題

一 例子 首先我們去編譯器試試 double a 1.9 通過新增監視檢視a的值 會發現a的值是1.8999999 二 開始今天的學習 在最開始學c 的時候並沒有對浮點數進行很深入的學習,認為浮點不就是小數嘛,首先在c 的巨集裡面有 flt max 和 flt min 的定義,float是四位元組的...

浮點數的精度問題

float 1bit 符號位 8bits 指數字 23bits 尾數字 double 1bit 符號位 11bits 指數字 52bits 尾數字 對於二進位制的小數 1.1 1 20 1 2 1 1 1 2 1.5 1.01 1 20 0 2 1 1 2 2 1 1 4 1.25 1.0011 1...

浮點數精度丟失問題

c 中的浮點數,分單精度 float 和雙精度 double float 是 system.single 的別名,介於 3.402823e38 和 3.402823e38 之間的32位數字,符合二進位制浮點演算法的 iec 60559 1989 ieee 754 標準 double 是 system...