您的位置 首页 php

卓象程序员:PHP中浮点数计算问题

一、序言

如果用php的+-*/计算 浮点数 的时候,可能会遇到一些计算结果错误的问题,比如echo intval( 0.58*100 );会打印57,而不是58,这个其实是计算机底层 二进制 无法精确表示浮点数的一个bug,是跨语言的,比如说 python 也会遇到这个问题。

例子:


二、浮点数表示规则

为啥输出是57? 首先我们要知道浮点数的表示(IEEE 754):

浮点数, 以64位的长度(双精度)为例, 会采用1位符号位(E), 11 指数 位(Q), 52位尾数(M)表示(一共64位).

符号位:最高位表示数据的正负,0表示正数,1表示负数。

指数位:表示数据以2为底的幂,指数采用偏 移码 表示

尾数:表示数据小数点后的有效数字.


三、浮点数二进制表示方式

这里的关键点就在于, 小数在二进制的表示方式:

将该数字乘以2,取出整数部分作为二进制表示的第1位;然后再将小数部分乘以2,将得到的整数部分作为二进制表示的第2位;以此类推,直到小数部分为0。

以0.625为例:

0.625* 2 = 1.25 —————- 1

0.25 * 2 = 0.5 —————— 0

0.5 *2 = 1.0 ——————- 1

小数部分为0,停止运算,0.625用二进制表示就是 0.101

以0.58为例:

0.58 * 2 = 1.16 ——————- 1

0.16 * 2 = 0.32 ——————- 0

0.32 * 2 = 0.64 ——————- 0

0.64 * 2 = 1.28 ——————- 1

0.28 * 2 = 0.56 ——————- 0

0.56 * 2 = 1.12 ——————- 1

0.12 * 2 = 0.24 ——————- 0

0.24 * 2 = 0.48 ——————- 0

…..

小数部分出现循环,无法停止,但是由于尾数最长只有52位,所以无法准确的表示0.57这个数,在从 二进制转换 回十进制时就是0.579999999… 那你*10之后intval一下, 自然就是57了….


四、结语

可见这个问题的关键点就是: “你看似有穷的小数, 在计算机的二进制表示里却是无穷的” so, 不要再以为这是PHP的bug了, 这就是这样的…..

文章来源:智云一二三科技

文章标题:卓象程序员:PHP中浮点数计算问题

文章地址:https://www.zhihuclub.com/153218.shtml

关于作者: 智云科技

热门文章

网站地图