使用C#,我有一些自定义类,我需要能够检测整数溢出并返回默认的最小值或最大值,具体取决于溢出是否是由于结果超过最大值或在最低价值下。我似乎无法找到关于如何检测任何地方发生的溢出“类型”的建议。
这些类分为两种常规类型:使用有符号值的类和使用无符号值的类。
例如,以下是处理Int32值的类之一:
public class Stat32Tf : IStat32T<float>
{
#region fields
private int baseValue, baseAdjustment;
private float baseMultiplier;
#endregion
#region ctors
public Stat32Tf()
{
baseValue = 0;
baseAdjustment = 0;
baseMultiplier = 1f;
}
public Stat32Tf(int baseValue, int baseAdjustment = 0, float baseMultiplier = 1f)
{
this.baseValue = baseValue;
this.baseAdjustment = baseAdjustment;
this.baseMultiplier = baseMultiplier;
}
#endregion
#region properties
public int BaseValue
{
get
{
return baseValue;
}
set
{
baseValue = value;
}
}
public int BaseAdjustment
{
get
{
return baseAdjustment;
}
set
{
baseAdjustment = value;
}
}
public float BaseMultiplier
{
get
{
return BaseMultiplier;
}
set
{
baseMultiplier = value;
}
}
public int TruncValue
{
get
{
return (int)Value;
}
}
public float Value
{
get
{
return (baseValue + baseAdjustment) * baseMultiplier;
}
}
#endregion
}
如您所见,类的概念是保存基值,调整值和乘数值,并返回Value属性中的聚合值。 (正如它所暗示的那样,TruncValue属性返回截断的整数值,删除任何小数值)。
目标是处理Value属性的“get”访问器中的溢出,如果结果超过max int值,则返回int.MaxValue,如果它低于min值,则返回int.MinValue,all没有抛出实际的溢出错误。使我变得棘手的部分是调整值和乘数也可能是负值(根据设计要求)。
实现这一目标的安全方法是什么?我找不到任何可以解决这种情况的资源。我猜测需要使用某种算术算法来确定结果是否会过高或过低。
答案 0 :(得分:2)
只有少数可能出现下溢的案例:
如果baseValue和baseAdjustment都是负数 - &gt;如果Int.MinValue - baseAdjustment&gt; baseValue然后你有一个下溢。
如果baseValue + baseAjustment为负且baseMultiplier为正 - >如果引发溢出异常,那么它只能是下溢。
如果baseValue + baseAdjustment为正,但baseMultiplier为负 - >如果引发溢出异常,那么它只能是下溢。
如果你想避免引发/捕获异常,那么它可能会有点复杂(你可能希望将结果转换为长期并将其与Int.MaxValue进行比较;这样它只会引发异常,如果结果超过Long.MaxValue)。
答案 1 :(得分:0)
花车非常大。您是否期望get值溢出或者您是否期望转换为int溢出?如果它只是演员类似下面的代码可能会有效。
//This answer is wrong, see below.
public int TruncValue
{
get
{
if (Value > (float)int.MaxValue)
{
return int.MaxValue
}
else if (Value < (float)int.MinValue)
{
return int.MinValue
}
else
{
return (int)Value;
}
}
}
虽然您可能需要对边缘情况进行一些额外的处理。
编辑 - 我在一些代码中使用了这个,发现了一些我没想到的行为,但显然它符合规范。
例如,
var Value = int.MaxValue + int.MaxValue //Ends up returning -2 with no exception in debug mode.
var MaxCalculatedValue = (int.MaxValue + int.MaxValue) * float.MaxValue //Ends up returning something like -3.4... ^38.
你真的可能需要将所有内容都转换为double,然后检查结果是否大于或小于int。
所以它可能看起来像这样:
public float Value
{
get
{
var result = ((double)baseValue + (double)baseAdjustment) * (double)baseMultiplier;
if (result > (double)int.MaxValue)
{
return (float)int.MaxValue)
}
if (result < (double)int.MinValue)
{
return (float)int.MinValue)
}
return (float)result;
}
}