php浮点型以及精度问题

浮点型(也叫浮点数 float,双精度数 double 或实数 real)

浮点数的形式表示:

LNUM [0-9]+
DNUM ([0-9]*[\.]{LNUM}) | ({LNUM}[\.][0-9]*)
EXPONENT_DNUM [+-]?(({LNUM} | {DNUM}) [eE][+-]? {LNUM})

浮点数的精度问题

浮点数的精度有限。尽管取决于系统,PHP 通常使用 IEEE 754 双精度格式,则由于取整而导致的最大相对误差为 1.11e-16。非基本数学运算可能会给出更大误差,并且要考虑到进行复合运算时的误差传递。
此外,以十进制能够精确表示的有理数如 0.1 或 0.7,无论有多少尾数都不能被内部所使用的二进制精确表示,因此不能在不丢失一点点精度的情况下转换为二进制的格式。这就会造成混乱的结果:例如,floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的 8,因为该结果内部的表示其实是类似 7.9999999999999991118...。
所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。

NaN

某些数学运算会产生一个由常量 NAN 所代表的结果。此结果代表着一个在浮点数运算中未定义或不可表述的值。任何拿此值与其它任何值进行的松散或严格比较的结果都是 FALSE。

由于 NAN 代表着任何不同值,不应拿 NAN 去和其它值进行比较,包括其自身,应该用 is_nan() 来检查。

浮点数比较的问题

永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等,但是你可以比较出浮点数的后几位是否相等

 1 <?php
 2 if((0.01 + 0.003) == 0.013)
 3     echo 'equal';
 4 else
 5     echo 'unequal';
 6 //结果为unequal
 7 /**
 8  * bccomp   比较做操作数和右操作数,以整型的形式返回结果
 9  * @param   string  $left_operand   左操作数
10  * @param   string  $right_operand  右操作数
11  * @param   int     $scale          用于比较小数点后的位数默认为2
12  * @return  int     0表示两个数是相等的,1表示左操作数大,-1表示右操作数大
13  **/
14 $iResult = bccomp((0.01 + 0.003), 0.013, 3); 
15 if(!$iResult)
16     echo 'the two operands are equal';
17 elseif($iResult > 0)
18     echo 'left_operand is larger than the right_operand';
19 elseif($iResult < 0)
20     echo 'right_operand is larger than the left_operand';
21 else
22     echo 'unknown result';
23 //the two operands are equal
24 ?>

 

posted @ 2015-06-24 11:33  zhaoyingnan911  阅读(986)  评论(0编辑  收藏  举报