为什么在VB.Net和Python中简单数学运算会返回意外(不准确)结果?

4 投票
4 回答
3127 浏览
提问于 2025-04-15 15:13
x = 4.2 - 0.1  

vb.net给出的结果是 4.1000000000000005
python也给出了 4.1000000000000005

而Excel给出的结果是 4.1
谷歌计算器给出的结果也是 4.1

这是什么原因呢?

4 个回答

4

其实没有什么问题,这只是浮点数的工作方式(它们内部的二进制表示)。总之:

>>> from decimal import Decimal
>>> Decimal('4.2')-Decimal('0.1')
Decimal('4.1')
10
>>> x = 4.2 - 0.1 
>>> x
4.1000000000000005

>>>>print(x)
4.1

这个问题的出现是因为 数字在计算机内部是如何存储的

计算机用二进制来表示数字,而我们人类习惯用十进制。对于浮点数,计算机需要对最接近的二进制浮点值进行一个 近似

几乎所有的机器(截至2000年11月)都使用IEEE-754浮点运算,几乎所有平台都把Python中的浮点数映射到IEEE-754的“双精度”格式。754双精度包含53位的精度,因此在输入时,计算机努力将0.1转换为最接近的分数,形式为 J/2***N*,其中 J 是一个包含正好53位的整数。

如果你用 print 输出这个数字,它会显示近似值,并且会被截断为一个 正常 的值。例如,真实0.1 的值是 0.1000000000000000055511151231257827021181583404541015625

如果你 真的 需要一个基于10的数字(如果你不知道这个问题的答案,你不需要),你可以在Python中使用 decimal.Decimal

>>> from decimal import Decimal
>>> Decimal("4.2") - Decimal("0.1")
Decimal("4.1")

二进制浮点运算有很多这样的惊喜。关于“0.1”的问题在下面的“表示错误”部分有详细解释。想了解其他常见惊喜,请查看 浮点数的危险

正如最后所说的,“没有简单的答案。”不过,不要过于担心浮点数!Python中的浮点运算误差是从浮点硬件继承而来的,在大多数机器上,每次操作的误差通常不会超过 2**53 的1部分。这对于大多数任务来说是足够的,但你需要记住这不是十进制运算,每次浮点运算都可能会出现新的舍入误差。

虽然确实存在一些特殊情况,但对于大多数普通的浮点运算使用来说,如果你简单地将最终结果的显示四舍五入到你期望的小数位数,最终你会看到你预期的结果。通常使用 str() 就足够了,如果需要更细致的控制,可以查看 str.format() 方法的格式说明符,具体见 格式字符串语法

15

浮点数/双精度。

你要记住,在二进制中,4.1 = 4 + 1/10。这里的1/10在二进制里是一个无限循环的和,就像在十进制中1/9是一个无限循环的和一样。

撰写回答