如何判断补码乘法溢出 + 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