时间:2021-05-26
浮点数运算精度问题
首先看一个例子:
<?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,错误
为什么会这样呢?
运算后,精度为20位时实际返回的内容如下:
<?php$a = 0.1;$b = 0.9;$c = 1;printf("%.20f", $a+$b); // 1.00000000000000000000printf("%.20f", $c-$b); // 0.09999999999999997780?>$c-$b 为 0.09999999999999997780,因此与0.1比较返回false
出现这个问题是因为浮点数计算涉及精度,当浮点数转为二进制时有可能会造成精度丢失。
浮点数转二进制方法
整数部分采用除以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方法处理后再比较
例子:
<?php$a = 0.1;$b = 0.9;$c = 1;var_dump(($c-$b)==$a); // falsevar_dump(round(($c-$b),1)==round($a,1)); // true?>2.使用高精度运算方法
首先进行运算时,使用高精度的运算方法,这样可以保证精度不丢失。
高精度运算的方法如下:
bcadd将两个高精度数字相加
bccomp比较两个高精度数字,返回-1,0,1
bcdiv将两个高精度数字相除
bcmod求高精度数字余数
bcmul将两个高精度数字相乘
bcpow求高精度数字乘方
bcpowmod求高精度数字乘方求模
bcscale 配置默认小数点位数,相当于Linux bc中的”scale=”
bcsqrt求高精度数字平方根
bcsub将两个高精度数字相减
例子:
<?php$a = 0.1;$b = 0.9;$c = 1;var_dump(($c-$b)==$a); // falsevar_dump(bcsub($c, $b, 1)==$a); // true?>以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文实例讲述了PHP中两个float(浮点数)比较方法。分享给大家供大家参考。具体如下:最近在开发一个合同管理系统的时候,涉及到两个浮点数比较,算是把我郁闷惨了
本文实例讲述了php判断两个浮点数是否相等的方法。分享给大家供大家参考。具体分析如下:由于浮点数直接用==判断是否相等是不完全正确的,所以下面给出了一个方法,先
1.浮点数的介绍float(浮点型)是Python基本数据类型中的一种,Python的浮点数类似数学中的小数和C语言中的double类型;2.浮点型的运算浮点数
上节课简单介绍了浮点数。计算机程序中的浮点数分为单精度浮点数和双精度浮点数。单精度和双精度精确的范围不一样。计算机里的最基本的存储单位用位(bit)来表示。bi
控制浮点数打印格式浮点数的打印和格式控制是sprintf的一大常用功能,浮点数使用格式符”%f”控制,默认保留小数点后6位数字,比如:复制代码代码如下:spri