1

使用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”访问器中的溢出,如果结果超过最大 int 值,则返回 int.MaxValue,如果低于最小值,则返回 int.MinValue,所有这些都不会抛出实际溢出错误。让我感到棘手的部分是调整值和乘数也可能是负值(根据设计要求)。

实现这一目标的安全方法是什么?我还没有找到任何资源来解决这种情况。我猜需要使用某种算术算法来确定结果是否超过或低于。

4

2 回答 2

3

只有少数情况下可能下溢:

  • 如果 baseValue 和 baseAdjustment 都是负数 -> 如果 Int.MinValue - baseAdjustment > baseValue 那么你有一个下溢。

  • 如果 baseValue + baseAjustment 为负且 baseMultiplier 为正 -> 如果引发溢出异常,则只能是下溢。

  • 如果 baseValue + baseAdjustment 为正但 baseMultiplier 为负 -> 如果引发溢出异常,则只能是下溢。

如果您想避免引发/捕获异常,那么它可能会更复杂一些(您可能希望将结果转换为 long 并将其与 Int.MaxValue 进行比较;这样它只会在结果超过时引发异常长。最大值)。

于 2013-04-11T13:07:51.933 回答
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.

您确实可能需要将所有内容都转换为双精度,然后检查结果是否大于或小于 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;
    }
}
于 2013-04-11T13:04:23.967 回答