为什么此检查的计算不会引发OverflowException? [英] Why does this checked calculation not throw OverflowException?

查看:41
本文介绍了为什么此检查的计算不会引发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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆