返回

揭开0.1+0.2不等于0.3背后的奥秘

前端

众所周知,在JavaScript中,0.1 + 0.2并不等于0.3。这非常容易求证。在Chrome控制台中输入0.1 + 0.2,显示的结果是0.30000000000000004。这似乎不是JavaScript的问题。在Java中,输入0.1 + 0.2也是这个数。

想要弄清楚这个问题,首先得清楚浮点型在计算机中是如何存储的。计算机使用二进制来表示数字。二进制只有0和1两种数字。要想表示一个十进制小数,需要把这个小数转换成二进制小数。

把十进制小数转换成二进制小数的方法是,先把整数部分转换成二进制整数,再把小数部分转换成二进制小数。整数部分的转换很简单,直接用二进制表示法表示即可。小数部分的转换比较复杂,需要用到一种叫做“尾数”的表示方法。

尾数就是小数点后面的数字。比如,0.1的尾数是1,0.2的尾数是2。尾数的二进制表示方法是,把尾数的每一位数字都转换成二进制数字,然后把这些二进制数字连接起来。比如,0.1的尾数是1,转换成二进制就是0.000...1。0.2的尾数是2,转换成二进制就是0.001。

把整数部分和尾数转换成二进制数字后,就可以把十进制小数转换成二进制小数了。二进制小数的格式是:

符号位 | 指数位 | 尾数位

符号位表示数字的正负。指数位表示数字的大小。尾数位表示数字的小数部分。

0.1的二进制表示是:

0 | 10000000 | 000...1

0.2的二进制表示是:

0 | 10000001 | 001

当计算机把0.1和0.2相加时,首先把它们转换成二进制小数,然后把二进制小数的尾数位相加。0.1的尾数位是0.000...1,0.2的尾数位是0.001,相加之后得到0.001...11。

这个二进制小数的尾数位超出了计算机能够表示的范围,所以计算机必须对它进行舍入。计算机的舍入方式是,把尾数位的最后一位数字舍去。如果最后一位数字是0,则舍去后尾数位不变;如果最后一位数字不是0,则舍去后尾数位进一位。

在0.1 + 0.2的例子中,尾数位的最后一位数字是1,所以舍去后尾数位进一位。进位之后,尾数位变成0.01。

把舍入后的尾数位转换成十进制小数,得到0.25。这就是为什么0.1 + 0.2不等于0.3的原因。

0.1 + 0.2不等于0.3的现象并不仅仅存在于JavaScript和Java中。在其他编程语言中,也会出现类似的现象。这是因为计算机的浮点数表示方式存在精度问题。

计算机的浮点数表示方式是有限的,它不能表示所有的小数。当计算机把一个十进制小数转换成二进制小数时,它必须对尾数位进行舍入。舍入会导致精度损失,从而导致计算结果与预期结果不符。

浮点数的精度问题在计算机科学中是一个非常重要的问题。它影响着许多领域的计算结果,比如科学计算、金融计算和图像处理等。为了解决浮点数的精度问题,计算机科学家们提出了许多不同的方法。其中一种方法是使用双精度浮点数。

双精度浮点数的尾数位比单精度浮点数的尾数位更多,所以它的精度更高。但是,双精度浮点数的计算速度也更慢。因此,在需要高精度的计算时,可以使用双精度浮点数;在不需要高精度的计算时,可以使用单精度浮点数。