php 浮點(diǎn)數(shù)比較方法詳解
浮點(diǎn)數(shù)運(yùn)算精度問題
首先看一個(gè)例子:
<?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,錯(cuò)誤
為什么會(huì)這樣呢?
運(yùn)算后,精度為20位時(shí)實(shí)際返回的內(nèi)容如下:
<?php
$a = 0.1;
$b = 0.9;
$c = 1;
printf("%.20f", $a+$b); // 1.00000000000000000000
printf("%.20f", $c-$b); // 0.09999999999999997780
?>
$c-$b 為 0.09999999999999997780,因此與0.1比較返回false
出現(xiàn)這個(gè)問題是因?yàn)楦↑c(diǎn)數(shù)計(jì)算涉及精度,當(dāng)浮點(diǎn)數(shù)轉(zhuǎn)為二進(jìn)制時(shí)有可能會(huì)造成精度丟失。
浮點(diǎn)數(shù)轉(zhuǎn)二進(jìn)制方法
整數(shù)部分采用除以2取余方法
小數(shù)部分采用乘以2取整方法
例如:把數(shù)字8.5轉(zhuǎn)為二進(jìn)制
整數(shù)部分是8
8/2=4 8%2=0
4/2=2 4%2=0
2/2=1 2%2=0
1比2小,因此不需要計(jì)算下去,整數(shù)8的二進(jìn)制為 1000
小數(shù)部分是0.5
0.5x2 = 1.0
因取整后小數(shù)部分為0,因此不需要再計(jì)算下去
小數(shù)0.5的二進(jìn)制為 0.1
8.5的二進(jìn)制為1000.1
計(jì)算數(shù)字0.9的二進(jìn)制
0.9x2=1.8
0.8x2=1.6
0.6x2=1.2
0.2x2=0.4
0.4x2=0.8
0.8x2=1.6
…. 之后不斷循環(huán)下去,當(dāng)截取精度為N時(shí),N后的數(shù)會(huì)被舍去,導(dǎo)致精度丟失。
上例中0.9在轉(zhuǎn)為二進(jìn)制時(shí)精度丟失,導(dǎo)致比較時(shí)出現(xiàn)錯(cuò)誤。
所以永遠(yuǎn)不要相信浮點(diǎn)數(shù)已精確到最后一位,也永遠(yuǎn)不要比較兩個(gè)浮點(diǎn)數(shù)是否相等。
正確比較浮點(diǎn)數(shù)的方法
1.使用round方法處理后再比較
例子:
<?php $a = 0.1; $b = 0.9; $c = 1; var_dump(($c-$b)==$a); // false var_dump(round(($c-$b),1)==round($a,1)); // true ?>
2.使用高精度運(yùn)算方法
首先進(jìn)行運(yùn)算時(shí),使用高精度的運(yùn)算方法,這樣可以保證精度不丟失。
高精度運(yùn)算的方法如下:
bcadd 將兩個(gè)高精度數(shù)字相加
bccomp 比較兩個(gè)高精度數(shù)字,返回-1,0,1
bcdiv 將兩個(gè)高精度數(shù)字相除
bcmod 求高精度數(shù)字余數(shù)
bcmul 將兩個(gè)高精度數(shù)字相乘
bcpow 求高精度數(shù)字乘方
bcpowmod 求高精度數(shù)字乘方求模
bcscale 配置默認(rèn)小數(shù)點(diǎn)位數(shù),相當(dāng)于Linux bc中的”scale=”
bcsqrt 求高精度數(shù)字平方根
bcsub 將兩個(gè)高精度數(shù)字相減
例子:
<?php $a = 0.1; $b = 0.9; $c = 1; var_dump(($c-$b)==$a); // false var_dump(bcsub($c, $b, 1)==$a); // true ?>
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持腳本之家!
- php判斷兩個(gè)浮點(diǎn)數(shù)是否相等的方法
- 簡(jiǎn)單談?wù)刾hp浮點(diǎn)數(shù)精確運(yùn)算
- PHP中兩個(gè)float(浮點(diǎn)數(shù))比較實(shí)例分析
- PHP中浮點(diǎn)數(shù)計(jì)算比較及取整不準(zhǔn)確的解決方法
- PHP浮點(diǎn)數(shù)精度問題匯總
- PHP數(shù)據(jù)類型之整數(shù)類型、浮點(diǎn)數(shù)的介紹
- PHP浮點(diǎn)數(shù)的一個(gè)常見問題
- php的sprintf函數(shù)的用法 控制浮點(diǎn)數(shù)格式
- php如何比較兩個(gè)浮點(diǎn)數(shù)是否相等詳解
相關(guān)文章
php返回相對(duì)時(shí)間(如:20分鐘前,3天前)的方法
這篇文章主要介紹了php返回相對(duì)時(shí)間的方法,可實(shí)現(xiàn)返回如:20分鐘前、3天前等格式時(shí)間,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04
php中用memcached實(shí)現(xiàn)頁面防刷新功能
這篇文章主要介紹了php中用memcached實(shí)現(xiàn)頁面防刷新功能,這是一個(gè)比較安全、穩(wěn)定的防刷新方案,需要的朋友可以參考下2014-08-08
解析smarty模板中類似for的功能實(shí)現(xiàn)
本篇文章是對(duì)smarty模板中類似for的功能實(shí)現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
PHP中的strtr函數(shù)使用介紹(str_replace)
PHP的 strtr 函數(shù), 性能要比 str_replace 函數(shù)高, 可以代替 str_replace 來使用2011-10-10

