C#int存储在double"=="精度问题中

lev*_*ovd 9 c# precision double int

这是简化的代码:

int i = 1;
double a = i;
double b = i;
Run Code Online (Sandbox Code Playgroud)

保证a == b真的吗?

Ian*_*nry 11

是.32位整数可以完全表示为64位浮点数.

  • 在任何情况下,即使计算中存在错误并且"i"是某些"关闭"值,您也要将"a"和"b"设置为它们,因此它们具有相同(可能不正确)的值.这就像问'double a = 1; double b = a;`,然后`a == b`?双精度错误可能很讨厌,但不是这样.即使你从`long`转换为'double`,你失去了精确度,`a`和`b`都会有相同的"不正确"值 - 在规范中找到这个也许是一个更有趣的问题. (2认同)

ags*_*mek 9

保证a == b是真的吗?

是.这是因为您执行两次相同的转换并给定其确定性行为,无论舍入问题如何,您都将得到相同的值.

我们可以将您的问题概括为:

我们可以对double没有精度松散的类型编码的32位整数值执行算术运算吗?

这个问题的答案也是肯定的.

一个简短的理由是,对尾数位的操作(参见http://en.wikipedia.org/wiki/Significand)是精确的,只要它是可能的,并且在32位整数值的情况下是可能的.

更长的故事来到这里.只要您的整数值适合称为尾数的小数部分的52位(请参阅http://en.wikipedia.org/wiki/Double_precision),所有使用double的整数值计算都将完全正常.

这是因为你的号码(比如说是0000010101101b二进制的173 )将被表示为1.010110100000b*2^7,这是准确的.

尾数上的所有操作都是直接的,只要它们适合尾数.当特定操作的结果不适合尾数时,发生对整数的舍入 - 例如.你会将40位的尾数乘以40位的尾数.当指数差异很大时,还会出现浮点运算的舍入.在这种情况下,即使是简单的加法操作也会因为matissas移位而失去精度.

返回以double - even除法运算编码的整数是精确的,只要结果是整数值.所以4.0/2.0 == 8.0/4.0也保证是真的.

当您的数字不是整数时,问题就开始了.但即使在这种情况下,如果它们是52位的形式x/2^y并且x适合52位(例如3/4 5/8 345/1024),则可以保证数字被精确地表示.y对于这两个操作数,对这些数字的操作也是精确的,因此即使:

123456789/1024/1024/1024/1024 == 
(23456789/1024/1024/1024/1024 +
100000000/1024/1024/1024/1024)
Run Code Online (Sandbox Code Playgroud)

保证是真的.

有趣的是,您可以安全地对54位有符号整数执行操作.这是因为您在开头有额外的位,其含义由指数编码,另外一位用于符号.现在-2 ^ 53在54位有符号整数的情况下将是MIN_INT不适合尾数,但指数将在这里完成尾数满零的工作.