Home  >  Article  >  Backend Development  >  为什么 PHP 和 JavaScript 取整 ((0.1+0.7)*10) 的结果不是 8?

为什么 PHP 和 JavaScript 取整 ((0.1+0.7)*10) 的结果不是 8?

WBOY
WBOYOriginal
2016-06-06 16:44:441593browse

php 代码

<span class="x">intval((0.7+0.1)*10) </span>

回复内容:

这和计算机的小数表示有关,

通常情况下,小数是用 浮点数 表示的:
计算机中的浮点数
浮点指的是带有小数的数值,浮点运算即是小数的四则运算,常用来测量电脑运算速度。大部份计算机采用二進制(b=2)的表示方法。位(bit)是衡量浮点数所需存储空间的单位,通常为32位或64位,分别被叫作单精度和双精度

比如单精度的浮点数,由32个bit位。按照IEEE 754 标准,32位中有
1位是符号位(sign)
8位是指数位(exponent)
23位是数值 (fraction)

如下图所示: 为什么 PHP 和 JavaScript 取整 ((0.1+0.7)*10) 的结果不是 8?
那么这个数的数值就是
(-1)^{sign} \times 2^{exponent_{2}} \times fraction_{2}
这样比如对于0.5,就可以表示成sign = 0, exponent = -1, fraction = 1
但实际上IEEE 754对表示方法还做了一些优化,比如fraction必须是1-2之间的一个小数,这样fraction就只用表示小数位,而exponent的实际值是exponent + offset.

这样实际的计算公式是:(-1)^{sign} \times 2^{exponent_{2} - 127_{10}} \times (1 + fraction_{2})
比如0.5的float表示为:
0 01111110 00000000000000000000000
其中0为符号位
01111110为指数位,十进制为126, 所以实际的exponent为126 - 127 = -1,
而 00000000000000000000000 为fraction,十进制为0,
所以0.5f = (-1)^{0} \times 2^{126 - 127} \times (1 + 0_{2})

这种表示方法带来的问题就是很多浮点数不能精确表示,比如0.1的浮点数表示为:
0 0111101 110011001100110011001101
实际上值为(-1)^{0} \times 2^{123- 127} \times (1 + 10011001100110011001101_{2})\approx 0.10000000149011612

你自己看看 `0.1 + 0.7` 的结果是什么?这跟浮点运算的特性有关。当十进制浮点数转换为二进制浮点数时,精度就可能丢失,运算结果肯定也是有误差的。

--

如果不明白为什么十进制浮点数转换为二进制浮点数,首先你可以选择回去看基础书……假若你是读计算机的话,并且还没有把书扔掉,或者还记得如何搜索。否则的话,大概就是这样的:浮点数都是保存为尾数乘以指数的形式的,例如 12345 会保存为 1.2345 * 10 ^ 4(实际保存 1.2345 和 10)。问题是,浮点数不是用十进制来保存尾数的,因此 1.2345 必须转化为对应的二进制形式,也就是类似于 1.01010011 这样的东西。你可以考虑一下,这种形式的二进制数只能表示 1 +/- 1/2 +/- 1/4 +/- 1/8 +/-... 因此,很有可能你要表达的那个十进制数,是在有限位数的二进制数中表现不出来的,然后精度就会丢失。 因为在这两种语言中,0.7 + 0.1 的结果小于 0.8,因此,取整后的结果为 7。

为什么 0.7 + 0.1 小于 0.8 ,可以看我在 在JS中,为什么浮点型数值0.1+0.2=0.30000000000000004,而0.15+0.15=0.25+0.05=0.3?中的回答
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn