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

时间:2009-10-20 14:25:03

标签: python vb.net floating-point

x = 4.2 - 0.1  

vb.net提供4.1000000000000005
python给出了4.1000000000000005

Excel提供4.1
Google calc提供4.1

这种情况发生的原因是什么?

4 个答案:

答案 0 :(得分:13)

Float/double precision.

你必须记住二进制,4.1 = 4 + 1/10。 1/10是二进制的无限重复和,很像1/9是十进制的无限和。

答案 1 :(得分:10)

>>> x = 4.2 - 0.1 
>>> x
4.1000000000000005

>>>>print(x)
4.1

这是因为how numbers are stored internally

计算机代表二进制数字,而不是十进制数字,正如我们人类习惯的那样。对于浮点数,计算机必须将近似值设置为最接近的二进制浮点值。

  

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

如果您print号码it will show the approximation被截断为正常值。例如,0.1真实值为0.1000000000000000055511151231257827021181583404541015625

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

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

二进制浮点运算有许多这样的惊喜。下面在“Representation Error”部分详细解释了“0.1”的问题。 有关其他常见意外的更完整说明,请参阅The Perils of Floating Point

     

正如接近结尾所说,“没有简单的答案。”不过,不要过分担心浮点数! Python浮点运算中的错误是从浮点硬件继承的,并且在大多数机器上每个操作的2**53不超过1个。这对于大多数任务来说已经足够了,但你需要记住它不是十进制算术,并且每次浮点运算都会遇到新的舍入错误。

     

虽然确实存在病态情况,但对于大多数临时使用浮点运算,如果您只是将最终结果的显示四舍五入到您期望的小数位数,您将看到最终期望的结果。 str()通常就足够了,为了更好地控制,请参阅str.format()Format String Syntax方法的格式说明符。

答案 2 :(得分:4)

真的没有问题。它只是浮动工作的方式(它们的内部二进制表示)。无论如何:

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

答案 3 :(得分:1)

在vb.net中,您可以通过使用Decimal类型来避免此问题:

Dim x As Decimal = 4.2D - 0.1D

结果是4.1。