最近代码中用到很多无符号整数的二元运算,一直提心吊胆的,生怕什么时候加法运算就溢出了。
所以有必要加个溢出检测。
关于溢出,http://www.phrack.com/issues.html?issue=60&id=10,这篇文章讲的很清楚。
检测无符号整数相加溢出的方法比较简单:
首先在无符号表示中 a + 2^n = a;
如果a,b两个无符号整数,都未溢出:a < 2^n, b < 2^n, 且a+b > 2^n,
那么sum = a + b - 2^n , 即sum - a = b - 2^n < 0==> sum < a,同理可得 sum < b。
用这样的方法可以判断两个无符号整数相加是否溢出,那么对于多个无符号整数相加,该怎么判断呢?我现在想到的比较笨的办法是两两相加然后判断……
上段代码,献丑一下……
1 //! @brief check whether the usinged add will result in overflow 2 template<typename input_iterator> 3 int is_unsinged_add_overflow(input_iterator begin, 4 input_iterator last) 5 { 6 typedef typename Iterator_Traits<input_iterator>::value_type value_type; 7 if(!(boost::is_same<value_type,size_t>::value) 8 && !(boost::is_same<value_type,unsigned int>::value) 9 && !(boost::is_same<value_type,unsigned long>::value) 10 && !(boost::is_same<value_type,unsigned short>::value)){ 11 return -1; 12 } 13 std::stack<value_type> temp_sum; 14 input_iterator it = begin; 15 while(it != last){ 16 value_type a = *it++; 17 if(it == last) { 18 temp_sum.push(a); 19 break; 20 } 21 value_type b = *it++; 22 value_type sum = a + b; 23 if(sum < a || sum < b) return 0; // overflow 24 temp_sum.push(sum); 25 } 26 while(!temp_sum.empty()){ 27 if(temp_sum.size() == 1) return 1;// no overflow 28 std::stack<value_type> forwad_sum; 29 while(!temp_sum.empty()){ 30 value_type a = temp_sum.top(); 31 temp_sum.pop(); 32 if(temp_sum.empty()) forwad_sum.push(a); 33 else{ 34 value_type b = temp_sum.top(); 35 temp_sum.pop(); 36 value_type sum = a + b; 37 if(sum < a || sum < b) return 0; // overflow 38 forwad_sum.push(sum); 39 } 40 } 41 swap(temp_sum,forwad_sum); 42 } 43 }
麻烦的traits,补上自己的偏特化……
1 template <typename T> 2 struct Iterator_Traits 3 { 4 typedef typename T::value_type value_type; 5 }; 6 7 template <typename type> 8 struct Iterator_Traits<type*> 9 { 10 typedef type value_type; 11 };
代码在ubuntu 11.04 64bit,g++-4.5.2下 编译通过,写的比较烂,请大家斧正~