為什麼php的浮點數運算不準確

王偉wayne發表於2017-02-09

關於php浮點數,經常遇見預算不準確的情況

例子:

//例子
$a = 10.601;
$b = 10.6009;
echo $a- $b;

// 結果如下
0.00010000000000154

結果錯誤,why?

why

根本原因, 在某些情況下,
2 進位制無法精確表示 10 進位制的小數部分。

把 10 進位制轉化為 2 進位制,需要進行如下換換算,下面以10.601為例

  • 整數部分

連續用該整數除以2,取餘數,然後商再除以2,直到商等於0為止。然後把得到的各個餘數按相反的順序排列。簡稱”除2取餘法”。

  • 小數部分

連續用改小數乘以2,取整數部分,然後小數部分再乘以2,直到小數部分為0為止 。然後把取出的整數部分按順序排列。簡稱”乘2取整法”。

10 (整數部分)

 
10/2=5---------0
5/2=2----------1
2/2=1----------0
1/2=1----------1

(10) 10=(1010) 2


0.601 小數部分

0.601*2=1.202 ----1
0.202*2=0.404 ----0
0.404*2=0.808 ----0
0.808*2=1.616-----1
0.616*2=1.232-----1
0.232*2=0.464-----0
0.464*2=0.928-----0
......

(0.601)10 = (0.10011001......)2

我們發現會無限的迴圈下去,沒法精確用2進位制標識

php浮點數

浮點數,以64位的長度(雙精度)為例, 會採用 1 位符號位(E), 11 指數位(Q), 52 位尾數(M)表示

  • 符號位:最高位表示資料的正負,0表示正數,1表示負數。
  • 指數位:表示資料以2為底的冪,指數採用偏移碼錶示
  • 尾數:表示資料小數點後的有效數字.

只能有52位儲存0.601部分,這樣大家就能看出原因了。

解決辦法

採用 “bc 資料函式” http://php.net/manual/zh/ref.bc.php

$a = 10.601;
$b = 10.6009;
//echo $a- $b;

echo bcsub($a , $b,4);


相關文章