【发布时间】:2020-09-01 03:59:41
【问题描述】:
这是我的代码int j:
void solve(){
unsigned long long n;
cin>>n;
unsigned long long sum = 0;
int j = 1;
for(int i=3;i<n+1;i+=2){
sum += ((4*i)-4)*(j);
j++;
}
cout<<sum<<"\n";
}
Input:
499993
Output:
6229295798864
但它给出了错误的输出,这是我的代码 long long j 工作正常:
void solve(){
int n;
cin>>n;
unsigned long long sum = 0;
long long j = 1;
for(int i=3;i<n+1;i+=2){
sum += ((4*i)-4)*(j);
j++;
}
cout<<sum<<"\n";
}
Input:
499993
Output:
41664916690999888
在这种情况下,j 的值远低于499993,它在int 范围内,但仍然无法正常工作。为什么会发生这种情况?
这里是实际problem 的链接。以防万一,你想看看。
【问题讨论】:
-
大概
((4*i)-4)*(j)产生的东西比int可以容纳的更大 -
更重要的是,直到实际赋值(由于
unsigned long long与int的等级),表达式才被提升为unsigned long long。评估期间的所有操作数都保留为int,结果(溢出)也是如此。您会发现,如果您更改了i而不是j,它同样会正确解析。 -
您似乎认为表达式不再“适合”给定类型时会自我提升。这不是语言的工作方式。隐式提升发生在操作数级别,在您的情况下,直到赋值才会发生。顺便说一句,您还可以将前导
4切换到4ULL(我想我是对的;我很少使用 UL 之外的文字常量),它也应该可以工作,留下i和j原样。关键是强制将该表达式提升到unsigned long long在分配之前。 -
long long的意义在于能够存储更大的整数值。这与整数表达式中的所有操作数都是纯ints 的事实完全无关。只要他们还在,操作就会在ints 上完成。事实上,你的程序中有一些其他变量是long long int,或者甚至表达式的结果将被分配给它,这一事实是无关紧要的,并且不会改变所有操作数都是ints 的事实,所以所有表达式将被如此评估。 -
顺便说一下,这通常是您应该避免使用无符号整数类型的情况。如果你的总和溢出,它可能会被忽视,因为它会简单地扭曲,产生一个不正确但看似可以接受的答案。
标签: c++ int overflow long-integer long-long