首頁  >  文章  >  後端開發  >  php 浮點數比較方法

php 浮點數比較方法

WBOY
WBOY原創
2016-07-30 13:30:02880瀏覽

浮點數運算精確度問題

首先看一個例子:

<code><span><span><?php</span><span>$a</span> = <span>0.1</span>;
<span>$b</span> = <span>0.9</span>;
<span>$c</span> = <span>1</span>;

var_dump((<span>$a</span>+<span>$b</span>)==<span>$c</span>);
var_dump((<span>$c</span>-<span>$b</span>)==<span>$a</span>);
<span>?></span></span></code>

$a+$b==$c 返回$a 回傳false
,錯誤為什麼會這樣呢? 運算後,精度為20位時實際回傳的內容如下:

<code><span><span><?php</span><span>$a</span> = <span>0.1</span>;
<span>$b</span> = <span>0.9</span>;
<span>$c</span> = <span>1</span>;

printf(<span>"%.20f"</span>, <span>$a</span>+<span>$b</span>); <span>// 1.00000000000000000000</span>
printf(<span>"%.20f"</span>, <span>$c</span>-<span>$b</span>); <span>// 0.09999999999999997780</span><span>?></span></span></code>
$c-$b 為

0.099999999999999977800精度,當浮點數轉為二進位時有可能會造成精度損失。

浮點數轉二進位方法整數部分採用除以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的二進位為

1000


小數部分是0.5


0.5x2 = 1.0 因取整後小數部分為0,因此不需要再計算下去 小數0.5的二進位為 0.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方法處理後再比較
例:

<code><span><span><?php</span><span>$a</span> = <span>0.1</span>;
<span>$b</span> = <span>0.9</span>;
<span>$c</span> = <span>1</span>;

var_dump((<span>$c</span>-<span>$b</span>)==<span>$a</span>);                   <span>// false</span>
var_dump(round((<span>$c</span>-<span>$b</span>),<span>1</span>)==round(<span>$a</span>,<span>1</span>)); <span>// true</span><span>?></span></span></code>

2.使用高精度運算方法
首先進行運算時,使用高精度的運算方法,這樣可以確保精度不會遺失。

高精度運算的方法如下: bcadd 將兩個高精度數字相加

bccomp 比較兩個高精度數字,回傳-1,0,1
bcdiv 將兩個高精度數字相除

bcmod 求高精度數字餘數

bcmul 將兩個高精度數字相乘

bcpow 求高精度數字乘方

bcpowmod 求高精度數字乘方求模
bcscale 配置預設小數點位數,相當於Linux bc中的”scale=”

bcsqrt 求高精準度數字平方根

bcsub 將兩個高精度數字相減

範例:

<code><span><span><?php</span><span>$a</span> = <span>0.1</span>;
<span>$b</span> = <span>0.9</span>;
<span>$c</span> = <span>1</span>;

var_dump((<span>$c</span>-<span>$b</span>)==<span>$a</span>);          <span>// false</span>
var_dump(bcsub(<span>$c</span>, <span>$b</span>, <span>1</span>)==<span>$a</span>); <span>// true</span><span>?></span></span></code>



版權聲明:本文為博主原創文章,未經博主允許不得轉載。


以上就介紹了php 浮點數比較法,包含了面向的內容,希望對PHP教學有興趣的朋友有幫助。


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn