PHP-浮点数的精度

PHP-浮点数的精度

浮点数的精度有限。尽管取决于系统,PHP 通常使用 IEEE 754 双精度格式,则由于取整而导致的最大相对误差为 1.11e-16。非基本数学运算可能会给出更大误差,并且要考虑到进行复合运算时的误差传递。

此外,以十进制能够精确表示的有理数如 0.1 或 0.7,无论有多少尾数都不能被内部所使用的二进制精确表示,因此不能在不丢失一点点精度的情况下转换为二进制的格式。这就会造成混乱的结果:例如,floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的 8,因为该结果内部的表示其实是类似 7.9999999999999991118...

所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。如果确实需要更高的精度,应该使用任意精度数学函数或者 gmp 函数

首先,给出一个任意实数,整数部分用普通的二进制便可以表示,这里只说小数部分如何表示

例如0.6

文字描述该过程如下:将该数字乘以2,取出整数部分作为二进制表示的第1位;然后再将小数部分乘以2,将得到的整数部分作为二进制表示的第2位;以此类推,知道小数部分为0。 
特殊情况: 小数部分出现循环,无法停止,则用有限的二进制位无法准确表示一个小数,这也是在编程语言中表示小数会出现误差的原因

下面我们具体计算一下0.6的小数表示过程

0.6 * 2 = 1.2 ——————- 1 
0.2 * 2 = 0.4 ——————- 0 
0.4 * 2 = 0.8 ——————- 0 
0.8 * 2 = 1.6 ——————- 1 
0.6 * 2 = 1.2 ——————- 1 
…………

我们可以发现在该计算中已经出现了循环,0.6用二进制表示为 1001 1001 1001 1001 …… 
如果是10.6,那个10.6的完整二进制表示为 1010.100110011001……

 

$a = '9717.30' * 100;
var_dump((int) $a) ;

$a = '1717.30' * 100;
var_dump((int) $a) ;


var_dump(0.9-0.8-0.1);
var_dump(price_format((0.9-0.8-0.1)));

#这个输出不是8 而是7,0.1在底层二进制相当于 0.1
var_dump(floor((0.1+0.7)*10) );




$x = 8 - 6.4;  // which is equal to 1.6
$y = 1.6;
var_dump($x == $y); // is not true



var_dump(round($x, 2) == round($y, 2)); // this is true

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值