2017-02-22 122 views
0

在C#:.NET double和python float有什么区别?

Console.WriteLine(1.2d - 1.0d); 

产生0.2。在python 3中:

print(1.2 - 1.0) 

产生0.19999999999999996

我的目标是在C#中编写与python 3产生相同浮点结果的快速代码。我显然对任何和所有浮点运算都感兴趣,而不仅仅是上面的例子。

什么是最实际的方法来实现呢?有我可以使用的图书馆吗?

另外,我想了解,究竟是什么导致了这种差异。两种表示都是64位,并且都是基于IEEE。那么这些实现有什么不同,使它们产生不同的结果?

参考文献:

+0

我建议你首先查看结果的按位表示,而不是字符串表示 - 直到你做完这些之后,没有证据表明减法结果实际上是任何不同的。但是您还需要明白,在C#中,JIT编译器允许在某些算术中使用更精确的表示形式,例如在执行多个64位操作时使用80位中间结果。如果你想在平台之间进行位兼容的算术,那将是棘手的。 –

+0

@JonSkeet,谢谢,这是个坏消息;( –

+0

FWIW,在Python 2中'0.2'被打印出来,但它的底层位模式相同,可以用'd = 1.2-1.0; print(format(d ,'0.60f'))''在两个版本中都打印出0.199999999999999955591079014993738383054733276367187500000000'。 –

回答

0

由于乔恩斯基特在COMM指出ents,你需要比较位表示。在C#中试用此功能:

Console.WriteLine($"{BitConverter.DoubleToInt64Bits(1.2d - 1.0d):X}"); 

结果:3FC9999999999998

现在在Python 3(的this answer提供):

import struct 
import binascii 
print(binascii.hexlify(struct.pack('>d', (1.2 - 1.0))).decode()) 

结果:3fc9999999999998

正如你所看到的,结果是一样的。

+0

在这种情况下,是的 - 但我的评论的另一个方面是,当你有复杂的计算时,中间结果会发生什么,这可能仍然是相关的(恐怕也可能发生在Python中) *发生时的规则是.NET中的具体实现。) –

+0

@JonSkeet了解。在一个不相关的说明中,你能告诉我,如何解释相同的位打印出不同的数字?是否有任何特定的(众所周知的)算法用于格式化输出的双精度? –

+1

对于.NET,调用'double.ToString()'相当于使用[G格式说明符](https://msdn.microsoft.com/en-us/library/dwhawy9k(v = vs.110).aspx #GFormatString) - 查看详情。我有一个[你可以使用的类](http://jonskeet.uk/csharp/DoubleConverter.cs),它将打印double的* exact *值 - 我不知道Python中是否有等价物。 –