【发布时间】:2014-09-01 11:20:39
【问题描述】:
好的,考虑以下场景:
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 有符号整数来表示分子和分母。如果尝试逼近的数字大于或小于RationalNumber 可以表示的最大或最小数字,即long.MaxValue 和long.MinValue,我希望我的方法抛出System.OverflowException。
我的第一次尝试非常简单和天真:
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 条件也不能解析为true。
我的第二次尝试更像是一种 hack(我觉得它有点丑),但考虑到算法需要做什么,如果 integerPart 和 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) 再次惨遭失败。最重要的是,这个解决方案远非完美,因为如果target 足够大,则可能会发生溢出而无需更改符号。
我确信必须有一种完全明显和愚蠢的方式来做到这一点,而我完全错过了它。有人可以告诉我方法并结束我在这个特定问题上的痛苦吗?
【问题讨论】:
标签: c#