最近在计算还款计划利率差,涉及两个浮点数的比较,结果令人百思不得其解,最终得出一个真理:“永远不要相信浮点数已精确到最后一位,也永远不要用等号比较两个浮点数是否相等”,详情如下:
1 |
|
输出结果如下:
1 | bool(false) |
出现这个是因为计算机底层二进制无法精确表示浮点数;
如下所示:
小数转二进制方法:
整数部分采用除以2取余方法
小数部分采用乘以2取整方法
如:8.4转二进制
整数部分是8:
8/2=4 8%2=0
4/2=2 4%2=0
2/2=1 2%2=0
1比2小,因此不需要计算下去,整数8的二进制为 1000
小数部分0.4:
0.4 * 2 = 0.8 => 0
0.8 * 2 = 1.6 => 1
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.2 * 2 = 0.4 => 0
0.4 * 2 = 0.8 => 0
0.8 * 2 = 1.6 => 1
0.6 * 2 = 1.2 => 1
0.2 * 2 = 0.4 => 0
1000.0110011001100110…….
这样一直循环下去,当截取精度为N时,N后的数会被舍去,导致精度丢失,
所以在上例中,8.4在计算机转为二进制时精度就已经丢失了,导致相减出的差值不等于1.6;
正确比较浮点数的方法:
1.使用round方法处理后再比较;
2.使用高精度运算方法;
1 |
|
输出结果如下:
1 | bool(true) |
php的官方原文地址:http://php.net/manual/zh/language.types.float.php
PHP 高精度函数