long long整数乘积范围问题:如何判断超1e18及是否为负?
问题与代码分析
我需要计算若干long long类型整数的乘积,这些整数的取值范围是0<=a[i]<=10^18,现在有两个问题需要解决:
- 如何判断该乘积是否超过
10^18? - 乘积是否会变为负数(
product<0)?
以下是我编写的测试代码:
#include<bits/stdc++.h> using namespace std; int main(){ int n; cin>>n; long long a[n],product=1; for(int i=0;i<n;i++){ cin>>a[i]; } sort(a,a+n); for(auto i:a){ product*=i; if(i==0) break; if(product>1000000000000000000) { cout<<-1; return 0; } } cout<<product; }
问题1:如何判断乘积是否超过10^18?
你的当前代码存在两个核心问题:
- 溢出后判断失效:当
product * i超过long long的最大值(约9e18)时,会触发整数溢出,溢出后的值会变成负数或乱码,此时再和1e18比较完全没有意义。 - 0的处理逻辑错误:遇到0就直接终止循环,但如果前面的乘积已经超过1e18,或者后续还有非0数,这种处理会导致错误结果。
正确的判断逻辑是在乘法执行前检查是否会溢出,具体规则:
对于当前乘积prod和下一个数x:
- 若
x == 0:乘积直接变为0,无需继续计算(0乘任何数都是0,不可能超过1e18)。 - 若
prod > 1000000000000000000LL / x:说明prod * x必然超过1e18,直接判定溢出。 - 否则:执行
prod *= x,继续计算。
问题2:乘积是否会变为负数?
根据题目给出的输入范围0<=a[i]<=10^18,所有输入数都是非负整数,因此它们的乘积必然是非负的,不可能出现负数。只有当输入允许负数时,才需要考虑乘积为负的情况。
修正后的代码
#include <iostream> #include <vector> using namespace std; const long long MAX_LIMIT = 1000000000000000000LL; int main() { int n; cin >> n; vector<long long> a(n); for (int i = 0; i < n; ++i) { cin >> a[i]; } long long product = 1; bool is_overflow = false; for (long long num : a) { if (num == 0) { product = 0; break; } // 提前检查乘法是否会溢出 if (product > MAX_LIMIT / num) { is_overflow = true; break; } product *= num; } if (is_overflow) { cout << -1 << endl; } else { cout << product << endl; } return 0; }
代码说明
- 用
vector替代变长数组long long a[n]:变长数组是C++标准的扩展特性,兼容性不如标准容器vector。 - 前置溢出检查:从根源避免溢出导致的错误判断。
- 明确的状态标记:用
is_overflow变量标记溢出状态,逻辑更清晰。
内容的提问来源于stack exchange,提问作者Humanware
相关产品推荐
相关产品推荐

