C++ long类型乘法溢出场景下ULL后缀的正确使用方法
问题根因
该报错本质是有符号整数运算溢出:
- 代码中
b、c均为long类型,在大部分32位编译环境、甚至部分64位Windows编译环境中,long为32位有符号整数,最大可表示值仅为2^31-1(约21亿) - 运算
b*c时,两个操作数都是long类型,会先以long类型执行乘法:输入为1000000000、1000000000、1时,b和c都是1000000000,乘积为1e18,远超过32位long的上限,运算阶段就已经触发溢出,后续赋值给unsigned long long类型的d也无法挽回溢出问题。
ULL的正确使用方法
ULL是C++中unsigned long long类型的字面量后缀,仅作用于数字字面量,作用是声明该字面量为64位无符号整数类型。当表达式中存在unsigned long long类型的操作数时,其他参与运算的整数类型会自动提升为unsigned long long,整个运算过程都在64位无符号整数的范围内执行,即可避免该场景下的溢出。
针对该代码的两种正确修正方案
方案1:在乘法运算开头加入1ULL,强制提升整个运算的类型
只需修改乘法一行即可,注意1ULL要放在运算的最左侧,保证第一个运算就触发类型提升:
d = 1ULL * b * c;
错误写法示例:
d = b * c * 1ULL;这种写法会先执行b*c的long类型运算,已经溢出后再和1ULL计算,无法解决问题。
方案2:直接将b、c声明为unsigned long long类型
从根源上保证运算的变量类型就是64位无符号整数:
#include <iostream> using namespace std; int main() { long n,m,a; cin >> n >> m >> a ; // 把b、c改成unsigned long long类型 unsigned long long b,c; b = (n%a==0)?(n/a):((n/a)+1); c = (m%a==0)?(m/a):((m/a)+1); unsigned long long d = b*c; cout<<d; }
常见使用注意事项
ULL只能加在数字字面量后面,不能加在变量名后面,比如bULL是非法写法- 涉及大数运算时,要保证类型提升发生在运算之前,不要等溢出后再做类型转换
- 如果运算结果超过
unsigned long long的上限(2^64-1,约1.8e19),还是会出现截断,需要根据题目范围选择更大的整数类型或者高精度实现。
内容的提问来源于stack exchange,提问作者Anmol
相关产品推荐
相关产品推荐

