首先來看一個範例:
<?php$a = 0.1;$b = 0.9;$c = 1; var_dump(($a+$b)==$c); var_dump(($c-$b)==$a);?>
$a $b==$c 回傳true,正確
$c-$b==$a 回傳false,錯誤
為什麼會這樣呢?
運算後,精確度為20位元時實際回傳的內容如下:
<?php$a = 0.1;$b = 0.9;$c = 1; printf("%.20f", $a+$b); // 1.00000000000000000000printf("%.20f", $c-$b); // 0.09999999999999997780?>
$c-$b 為0.09999999999999997780,因此與0.1比較回傳false
#出現這個問題是因為浮點數計算涉及精確度,當浮點數轉為二進位時有可能會造成精確度損失。 浮點數轉二進位方法
整數部分採用除以2取餘
方法
小數部分採用
乘以2取整
方法
例如:
把數字8.5轉為二進位
整數部分是8 8/2=4 8%2 =0 4/2=2 4%2=0 2/2=1 2%2=0
1比2小,因此不需要計算下去,整數8的二進位為小數部分是0.5 0.5x2 = 1.0
因取整後小數部分為0,因此不需要再計算下去
1000.1
8.5
1000.1
計算數字0.9的二進位
0.9x2= 1.8 0.8x2=1.6 0.6x2=1.2
0.2x2=0.4 0.4x2=0.8 0.8x2=1.6
…. 之後不斷循環下去,當截斷精確度為N時,N後的數會被捨去,導致精度遺失。 上例中0.9在轉為二進位時精確度遺失,導致比較時發生錯誤。
所以永遠不要相信浮點數已精確到最後一位,也永遠不要比較兩個浮點數是否相等。
正確比較浮點數的方法
#1.使用round方法處理後再比較
範例:
<?php$a = 0.1;$b = 0.9;$c = 1; var_dump(($c-$b)==$a); // falsevar_dump(round(($c-$b),1)==round($a,1)); // true?>
首先進行運算時,使用高精度的運算方法,這樣可以保證精度不會遺失。
高精準度運算的方法如下:
bcadd 將兩個高精準度數字相加
bccomp
bcp 將兩個高精準度數字相除
<?php$a = 0.1;$b = 0.9;$c = 1; var_dump(($c-$b)==$a); // falsevar_dump(bcsub($c, $b, 1)==$a); // true?>
以上是關於php 浮點數比較方法 的講解的詳細內容。更多資訊請關注PHP中文網其他相關文章!