如何判斷補碼乘法溢出 + hack網上若干做法


網上的很多代碼都是錯的,我來hack一波

因為UB的問題,很多代碼看起來是對的,但是在O2或者別的情況下很容易出問題
c\c++的補碼溢出是UB,但無符號溢出不是UB
注意這樣的細節,不然很容易翻車

https://www.cnblogs.com/klzwj1988/archive/2011/09/12/2174134.html

hack數據 10,INT32_MIN
原因:沒有處理-INT32_MIN未定義的情況,大多數情況下-INT32_MIN = -INT32_MIN,直接死循環

https://blog.csdn.net/weixin_30670151/article/details/96988831

hack數據 INT32_MIN,10
原因:條件不對

常見判斷有符號乘法溢出的問題

1.a * b == INT_MIN 當a取INT32_MIN,很容易出問題,正確的姿勢是用除法來判斷乘法溢出
2.INT32_MIN / a 當a = -1的時候,直接乘法溢出....很多代碼都沒有考慮到這個情況....
3.一般情況-INT32_MIN = INT32_MIN,很多人在化負數為整數的時候,沒有考慮到這一點....

吐槽

網上一堆代碼抄來抄去....錯誤的很多...吐了

hack數據

兩層for暴力枚舉check即可,數據很強

using ll = long long int;
vector<ll> v = {10,10,INT64_MAX,INT64_MIN,0,INT32_MAX,INT32_MIN,100,-100,INT32_MAX / 2,INT32_MIN / 2,INT64_MAX / 2,INT64_MIN / 2,3,-3,-INT64_MAX,-1,1,2,-2,-3,-10,1ll * INT32_MAX * (INT32_MAX - 10),1ll * INT32_MAX * INT32_MAX * 1ll,1ll * INT32_MIN * INT32_MAX,123456789101112ll,-1234567891234578ll-1234568,12345645,123544515555ll,1ll * INT32_MIN / INT32_MAX,1ll * INT32_MAX * 123454,1ll * INT32_MIN * 1231121,12313,INT32_MIN / 8 * 1ll - 100,1ll * INT32_MIN * 8 * 1ll + 1};

正確的代碼

#include <numeric>
#include <iostream>
#include <algorithm>
template<typename T,typename T2>
bool is_mul_overflow(T a,T2 b) {
  	static_assert(std::is_same<T,T2>::value,"is_mul_overflow[類型不匹配]");
  	
  	using std::numeric_limits;
  	
  	if (a == -1) {
  		return (b == numeric_limits<T>::min());
	}
  	else if (b == -1) {
  		return (a == numeric_limits<T>::min());
	}
  	else if (a >= 0 and b >= 0) {
  		return a == 0 ? 0 : numeric_limits<T>::max() / a < b;
	}
	else if(a < 0 and b < 0) {
		return numeric_limits<T>::max() / a > b;
	} 
	else if (b < 0) {
		return numeric_limits<T>::min() / b < a;
	}
	else {
		return numeric_limits<T>::min() / a < b;
	} 
}
int main() {
  	std::cout << is_mul_overflow(10,500000000);
  	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM