如何检测潜在的溢出

时间:2014-09-01 11:20:39

标签: c#

好的,请考虑以下情况:

 public static bool TryGetNearestRationalNumber(double target, double precision, out RationalNumber nearest)
 {
     //implements continued fractions to solve the problem. Only relevant code is shown.

     var integerPart = (long)target; //necessary for algorithm
     var fractionalPart = target - integerPart; //necessary for algorithm,
     ....
 }

RationaNumber内部使用两个Int64有符号整数来表示分子和分母。如果尝试的近似数字大于或小于System.OverflowException可以表示的最大或最小数字RationalNumber和{{1},我希望我的方法抛出long.MaxValue }}

我的第一次尝试非常简单和天真:

long.MinValue

当我致电 public bool TryGetNearestRationalNumber(double target, double precision, out Foo foo) { //check overflow here if (target > long.MaxValue || target < long.MinValue) throw new OverFlowExcetpion(); //implements continued fractions to solve the problem. Only relevant code is shown. var integerPart = (long)target; //necessary for algorithm var fractionalPart = target - integerPart; //necesarry for algorithm, ... } TryGetNearestRationalNumber(1f + long.MaxValue, precision, nearest)时,这很难过。显然,这是因为对于如此大或小的数字,TryGetNearestRationalNumber(-1f + long.MinValue, precision, nearest)没有足够的分辨率来检测潜在的溢出,并且double条件都没有解析为if。< / p>

我的第二次尝试更多的是黑客攻击(我发现它有点丑陋)但考虑到算法需要做什么,如果trueintegerPart没有做到,我可以检测到溢出有相同的标志;这必然意味着发生了溢出。所以我的第二次尝试看起来像这样:

target

问题是这也不会奏效。它适用于最大值溢出 public bool TryGetNearestRationalNumber(double target, double precision, out Foo foo) { //implements continued fractions to solve the problem. Only relevant code is shown. var integerPart = (long)target; //necessary for algorithm if ((integerPart < 0 && target > 0) || (integerPart > 0 && target < 0)) //yuck! throw new OverFlowException(); var fractionalPart = target - integerPart; //necesarry for algorithm, } ,但在最小值溢出TryGetNearestRationalNumber(1f + long.MaxValue, precision, nearest)时再次失败。最重要的是,这个解决方案远非完美,因为给定足够大的TryGetNearestRationalNumber(-1f + long.MinValue, precision, nearest),溢出可以在不改变符号的情况下发生。

我确信必须有一种完全明显和愚蠢的方式来做到这一点,我完全错过了它。有人可以告诉我道路并结束我对这个特殊问题的痛苦吗?

1 个答案:

答案 0 :(得分:1)

ckecked关键字可以帮助您的代码在运行时通过抛出OverflowException来捕获溢出。

// Checked block. 
checked
{
    int i3 = 2147483647 + 10; // throws
    Console.WriteLine(i3);
}

在与另一个线程的usr讨论之后,我们可以推断为了在double中捕获long值下限的溢出,你必须下到1025d - long.MinValue。所以看起来您的下限必须考虑到十进制类型的尾数大小才能正确地回转到long

作为一种解决方法,它是非常讨厌的,并且不会产生非常易读的代码......