现在的位置: 首页 > 综合 > 正文

检查加法是否溢出

2018年03月22日 ⁄ 综合 ⁄ 共 1664字 ⁄ 字号 评论关闭

方法一:

境遇:假设要判断两个整数的加法运算是否溢出。

C#中的checked/unchecked关键字能和方便的检查运算是否溢出,但是我们在C++中怎么做呢?溢出也不像C#会抛出异常,别忘了C/C++的特点:我们可以直接操纵底层硬件!把寄存器溢出标志位取出来就可以了。虽然只对加法做了溢出判断,但有了下面这段示例也能判断其它运算的溢出了。

 

//Copyright By Renjiachao
//By Renjiachao 2010-10-13
#include<iostream>
#include<string>
using namespace std;
 
class SafeInt //signed int
{
    friend const SafeInt operator+(const SafeInt& lhs, const SafeInt& rhs);
    friend ostream& operator<<(ostream& out, const SafeInt& si)
    { out<<si.val; return out; }
public:
    SafeInt(int v=0):val(v) {}
    operator int() {return val;}
    SafeInt& operator+=(const SafeInt& rhs)
    {
        val += rhs.val;
        unsigned   long   dwEAX   =   0; 
        __asm //汇编代码鸣谢:贾宁宇
        {
            PUSH   EAX  //压入EAX寄存器的值作为保护 
            PUSHFD  //将EFLAGS寄存器的全部内容压入堆栈
            POP   EAX   //把刚刚入栈的EFLAGS寄存器的值取出放入EAX
            MOV   dwEAX,EAX   //把EAX中的值放入dwEAX变量中
            POP   EAX   //恢复EAX寄存器的值
        }
        if (dwEAX & 0x00000800)   //取出第11(基于0)位的值
            throw overflow_error("溢出");
        return *this;
    }
private:
    int val;
};
const SafeInt operator+(const SafeInt& lhs, const SafeInt& rhs)
{
    SafeInt temp(lhs);
    temp+=rhs;
    return temp;
}
int main()
{ 
    SafeInt i1 = 10;
    SafeInt i2 = INT_MAX - 11;
    SafeInt iSum = 0;
    try
    {
        iSum = i1 + i2;  //不溢出
        cout<<i1<<" + "<<i2<<" = "<<iSum<<endl;
        iSum = iSum + i1;   //溢出
        cout<<i1<<" + "<<i2<<" = "<<iSum<<endl;
    }
    catch(overflow_error & e)
    {
        cout<<e.what()<<endl;
    }
    return 0;
}

代码中的说明:

OF--溢出标志

EFLAGS 寄存器
的标志位大致如下表所示:


方法二:

if ((unsigned)a+(unsigned)b > INT_MAX)

                   complain();

此处的INT_MAXSHI是一个已定义的常量,代表可能的最大整数值。ANSI C标准在<limits.h>中定义了INT_MAX;如果是在其他C语言实现上,你也需要自己重新定义。

 不需要用到无符号算术运算的另一种可行方法是:

           

if (a > INT_MAX -B)

                         complain();

方法三:

static PyObject *
int_add(PyIntObject *v, PyIntObject *w)
{
    register long a, b, x;
    CONVERT_TO_LONG(v, a);
    CONVERT_TO_LONG(w, b);
    /* casts in the line below avoid undefined behaviour on overflow */
    x = (long)((unsigned long)a + b);
    if ((x^a) >= 0 || (x^b) >= 0)
        return PyInt_FromLong(x);
    return PyLong_Type.tp_as_number->nb_add((PyObject *)v, (PyObject *)w);
}


抱歉!评论已关闭.