以下是简化代码:
int i = 1;
double a = i;
double b = i;
是否保证a == b
为真?
答案 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^y
和x
适合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的测试,但我怀疑你会使用那些大数字。