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位浮点数.
保证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不适合尾数,但指数将在这里完成尾数满零的工作.