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

时间:2010-11-27 08:31:06

标签: c# double int precision

以下是简化代码:

int i = 1;
double a = i;
double b = i;

是否保证a == b 为真

4 个答案:

答案 0 :(得分:11)

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

答案 1 :(得分:9)

  

是否保证a == b是真的?

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

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

  

我们可以对double类型编码的32位整数值进行算术运算而不会出现精度松散吗?

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

简短的理由是,如果只有可能的话,对尾数位(参见http://en.wikipedia.org/wiki/Significand)的操作是精确的,如果是32位整数值则可以。

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

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

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

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

当您的号码不是整数时,问题就开始了。但即使在这种情况下,如果数字是x/2^yx适合52位的形式(例如3/4 5/8 {{1},则可以保证精确表示数字。 })。这些数字的操作也是精确的,因为345/1024对于两个操作数都是相等的,所以即使:

y

保证是真的。

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

答案 2 :(得分:3)

是的,您可以在double(64位浮点数)中存储(32位)整数,而不会丢失精度。

但是,只要使用double执行计算,就很可能会引入舍入误差,即精度损失。这些错误可能会很小,以便在您将double值转换回int时将它们弄平 - 但错误就在那里,所以要注意它。

如何完成:有关如何将整数存储为浮点值的详细信息,请参阅this document (IEEE Standard 754 Floating Point Numbers by Steve Hollasch)

总结(有些不准确),浮点值由三部分组成:符号位,“小数”部分(称为尾数)和“指数”部分。它们大致如下:

= -1 符号位 ×分数×2 exponent

您可以将整数值存储在double的“分数”部分中(这是52位宽,对于32位整数来说,它足够宽。“指数”部分可以只是设置为0,因为它不需要。

答案 3 :(得分:-2)

我打开了Visual Studio,并对其进行了测试。

这是我的代码:

int i = 5;
double t = i;
double k = i;
MessageBox.Show((i == t).ToString()); //true
MessageBox.Show((k == t).ToString()); //true
i += 5;
t += 5;
k = i;
MessageBox.Show((i == t).ToString()); //true
MessageBox.Show((k == t).ToString()); //true
i += (int)Math.Round(5.6);
t += 5.6;
t = (int)Math.Round(t);
k = i;
MessageBox.Show((i == t).ToString()); //true
MessageBox.Show((k == t).ToString()); //true
i = int.MaxValue - 5438;
t = int.MaxValue - 5438;
k = i;
MessageBox.Show((i == t).ToString()); //true
MessageBox.Show((k == t).ToString()); //true
i = (int)Math.Round(double.MaxValue);
t = Math.Round(double.MaxValue);
k = i;
MessageBox.Show((i == t).ToString()); //false
MessageBox.Show((k == t).ToString()); //false
i = (int)Math.Round(double.MaxValue);
t = i;
k = i;
MessageBox.Show((i == t).ToString()); //true
MessageBox.Show((k == t).ToString()); //true

结果是两个消息框说的是真的。

我想结论是:是的,你可以保证这是真的。

编辑:稍微扩展我的测试。返回false的唯一测试是double.MaxValue的测试,但我怀疑你会使用那些大数字。