防止算术上溢下溢的最有效方法是什么?

我想到的一些例子是:

  • 根据有效输入范围进行测试
  • 使用形式方法进行验证
  • 不变量的使用
  • 使用语言功能或库在运行时进行检测(这不会阻止它)

===============>>#1 票数:3 已采纳

一种可能性是使用一种具有任意大小的整数的语言,该整数从不上溢/下溢。

否则,如果这是您真正关心的事情,并且如果您的语言允许,请编写一个包装器类,其作用类似于整数,但检查每个操作是否溢出。 您甚至可以让它对调试版本进行检查,并为发布版本进行优化。 在像C ++这样的语言中,您可以执行此操作,并且它的行为几乎与发行版的整数类似,但是对于调试版,您将获得完整的运行时检查。

class CheckedInt
{
private: 
    int Value;

public:
    // Constructor
    CheckedInt(int src) : Value(src) {}

    // Conversions back to int
    operator int&() { return Value; }
    operator const int &() const { return Value; }

    // Operators
    CheckedInt operator+(CheckedInt rhs) const
    {
        if (rhs.Value < 0 && rhs.Value + Value > Value)
            throw OverflowException();
        if (rhs.Value > 0 && rhs.Value + Value < Value)
            throw OverflowException();
        return CheckedInt(rhs.Value + Value);
    }

    // Lots more operators...
};

编辑:

事实证明有人已经在使用C ++进行此操作 -当前的实现主要针对Visual Studio,但看起来他们也正在获得对gcc的支持。

===============>>#2 票数:1

我编写了许多测试代码以对代码进行范围/有效性检查。 这往往会遇到大多数这类情况-绝对可以帮助我编写更多的防弹代码。

===============>>#3 票数:1

使用像长double一样的高精度浮点数。

===============>>#4 票数:1

我认为您在列表中缺少一个非常重要的选择:为工作选择正确的编程语言。 许多编程语言都没有这些问题,因为它们没有固定大小的整数。

===============>>#5 票数:0

在许多情况下,检查不一致的包装器是有意义的。 如果对两个或多个整数的加法运算(即加法或乘法)导致值小于操作数,那么您就知道出了问题。 每个加法运算之后,

if (sum < operand1 || sum < operand2)
    omg_error();

同样,应该检查在逻辑上应导致较小值的任何操作,以查看是否意外插入了该操作。

===============>>#6 票数:0

选择使用哪种语言时,还有比整数大小更重要的考虑因素。 如果您不知道该值是否在范围内,则只需检查您的输入即可;如果这种情况极为罕见,则可以使用异常处理。

===============>>#7 票数:0

您是否研究过使用形式化方法检查代码以证明其没有溢出? 一种称为抽象解释的形式化方法技术可以检查软件的健壮性,以证明您的软件不会遭受溢出,下溢,被零除,溢出或其他类似的运行时错误的困扰。 这是一种数学技术,可以详尽地分析您的软件。 该技术由Patrick Cousot在1970年代率先提出。 它成功地用于诊断Arian 5火箭的溢流情况,其中溢流导致了运载火箭的毁灭。 溢出是在将浮点数转换为整数时引起的。 您可以在此处以及在Wikipedia上找到有关此技术的更多信息。

  ask by Chris de Vries translate from so

未解决问题?本站智能推荐:

2回复

算术溢出

为什么使用二进制补码加正数和负数时不会发生算术溢出。 如果可以,请提供带有8位带符号整数(字节)的示例。
3回复

无符号数的溢出/下溢

因此,如果你在无符号数字上加上1,你就会溢出,如果你有一个带有减法的0,你就已经下溢了。 这种情况在每种情况下都适用吗? 如果你做5-0:0101 -0000 = 0101 +(1111 + 1) = 0101 +0000 = 0101 ...这里有一个零,而不是1.如
1回复

是否有任意精度算术的通用实现策略,无论特定语言如何都是有效的?

我正在考虑实现任意精度算术的不同方法(有时称为Bignum,Integer或BigInt)。 似乎常见的习惯是使用数组来存储实际值,并在空间需求增长或缩小时根据需要重新分配它。 更准确地说,似乎数组元素的位大小通常是通常支持的第二大尺寸(使溢出计算可能更容易实现?),例如语言/平台支
1回复

查找数最大的素数的最有效方法600851475143

我试图找到最大的素数600851475143,并成功使用下面的代码,但是我知道这是一种残酷的方式,可能有更有效,更优雅的方法来解决此问题。 但是,我想不出任何办法,希望有人可以分享他们的解决方案并附上解释。
1回复

如果我知道x,最有效的搜索x + y = x * y结果的方法是什么?

例如: 我想尝试编写一个程序来搜索结果,例如搜索素数: 但是程序有一些问题: 它只能在-10到10之间搜索结果,因为Float.MIN_VALUE和Float.MAX_VALUE之间的搜索太慢 我知道9 + 1.125 = 9 * 1.125,但是即使我将每个增
1回复

以二进制加法进出最高有效位

我有这个二进制加法问题, = 100101需要5位答案,因此应将1减去00101,因为已经发生了溢出。 然后它问, 进位到最高有效位有什么价值? 最高有效位的进位价值是什么? 我以为这两个都是1,谁能澄清一下, 我通过算术并查看最高有效位的进位和出位得到了答
7回复

整数的最快c算术方法

我正在写ac程序。 我有一个无符号整数(16位),其值可以是任何时候任何东西,我有一个签名字符(8位),其值可以是任何时候,在数据类型的明显限制内。 我需要将signed char添加到unsigned int,结果是unsigned int,如果值溢出超过0xFFFF或低于0x00,我需要
2回复

算术溢出硬件中断?

我们这些知道Carry and Overflow标志的人(不要忘记标志和零)喜欢他们。 我的问题是,如果设置了进位或溢出标志,是否有CPU会中断? 什么时候问它? 它的方法比在每个算术指令后都有一个分支更好...
2回复

C#算术问题

下午好, 从来没有用C#做过严肃的数学工作,我刚刚注意到让我困惑的事情......如果确实如此 等于4294967296.0,也就是UInt32.MaxValue + 1 ,为什么会这样 等于1? 乍一看,在我看来溢出发生在这里......但是为什么那个产品应该适合UIn
1回复

查找计数时的算术溢出错误

尝试查找其计数时遇到了以下错误。 对于此查询: V_Material是一个视图