为什么舍入浮点数1.4999999999999999产生2?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么舍入浮点数1.4999999999999999产生2?相关的知识,希望对你有一定的参考价值。

我一直在读一本书Write Great code - Understanding the Machine。关于四舍五入的部分说:

如果十进制位值大于或等于可以表示的总十进制值的一半,则数字应舍入为最小的较大数字。

意思是:

round(1.5) // equals 2
round(1.49) // equals 1

但是当我用Python尝试这个时:

x1 = 1.4999  # rounds to 1

x2 = 1.4999999999999999  # rounds to 2

print(round(x1))

print(round(x2))

输出是:

1

2

我用C#和Swift尝试了同样的东西,它给出了相同的输出。所以我认为这是一个与语言无关的话题。

但为什么会这样呢?

我的假设是浮点单元对应用程序员舍入之前将“1.4999999999999999999”转换为“1.5”的额外位进行舍入。

答案

x2 = 1.4999999999999999print(round(x2))中,有两个操作会影响价值。 round功能不能直接在数字1.4999999999999999或数字“1.4999999999999999”上操作。其操作数必须采用Python实现使用的浮点格式。

因此,首先,将1.4999999999999999转换为浮点格式。 Python对Python实现使用哪种浮点格式并不严格,但IEEE-754基本64位二进制格式很常见。在此格式中,最接近的可表示值为1.4999999999999999为1.5和1.4999999999999997779553950749686919152736663818359375。前者比后者更接近1.4999999999999999,所以使用前者。

因此,将1.4999999999999999转换为浮点格式会产生1.5。然后round(1.5)产生2。

以上是关于为什么舍入浮点数1.4999999999999999产生2?的主要内容,如果未能解决你的问题,请参考以下文章

舍入浮点数的源代码

使用 0.5 规则舍入浮点数的方法

用 f 字符串舍入浮点数 [重复]

舍入浮点数,然后转到语言环境字符串

如何在PHP中舍入浮点数?

C中的printf如何对浮点数进行舍入?