为什么此检查的计算不会引发OverflowException? [英] Why does this checked calculation not throw OverflowException?
问题描述
有人可以解释以下行为吗?
Can somebody please explain the following behavior:
static void Main(string[] args)
{
checked
{
double d = -1d + long.MinValue; //this resolves at runtime to -9223372036854780000.00
//long obviousOverflow = -9223372036854780000; //compile time error, '-' cannot be applied to operand of tpye ulong -> this makes it obvious that -9223372036854780000 overflows a long.
double one = 1;
long lMax = (long)(one + long.MaxValue); // THROWS
long lMin = (long)(-one + long.MinValue); // THEN WHY DOES THIS NOT THROW?
}
}
我不明白为什么我在最后一行代码中没有得到 OverFlowException
.
I don't undersant why I'm not getting an OverFlowException
in the last line of code.
更新,更新了代码,以使检查清楚,除了最后一种情况外,在将double转换为long时,checked都可以通过.
UPDATE Updated code to make it obvious that checked does through when casting a double to long except in the last case.
推荐答案
您正在使用 double
值( -1d
)进行计算.浮点数不会在.NET上抛出. checked
对它们没有任何影响.
You are calculating with double
values (-1d
). Floating point numbers do not throw on .NET. checked
does not have influence on them in any way.
但是转换回 long
的过程受 checked
的影响. one + long.MaxValue
不适合 double
的范围. -one + long.MinValue
确实在该范围内.这样做的原因是带符号的整数具有更多的负数而不是正数. long.MinValue
没有等价的正数.这就是为什么代码的负版本恰好适合而正版本不适合的原因.
But the conversion back to long
is influenced by checked
. one + long.MaxValue
does not fit into the range of double
. -one + long.MinValue
does fit into that range. The reason for that is that signed integers have more negative numbers than positive numbers. long.MinValue
has no positve equivalent. That's why the negative version of your code happens to fit and the positive version does not fit.
加法运算不会更改任何内容:
The addition operation does not change anything:
Debug.Assert((double)(1d + long.MaxValue) == (double)(0d + long.MaxValue));
Debug.Assert((double)(-1d + long.MinValue) == (double)(-0d + long.MinValue));
我们正在计算的数字超出了 double
精确范围的范围. double
可以精确地拟合最大2 ^ 53的整数.我们这里有四舍五入错误.加一等于加零.本质上,您正在计算:
The numbers we are calculating are outside of the range where double
is precise. double
can fit integers up to 2^53 precisely. We have rounding errors here. Adding one is the same as adding zero. Essentially, you are computing:
var min = (long)(double)(long.MinValue); //does not overflow
var max = (long)(double)(long.MaxValue); //overflows (compiler error)
添加操作是红色鲱鱼.它不会改变任何东西.
The add operation is a red herring. It does not change anything.
这篇关于为什么此检查的计算不会引发OverflowException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!