关于左移位运算超过数字范围的坑
CSP2020提高组T2,洛谷题号P7076动物园,有一个同学不管怎么做都是95分。
这个同学程序里面有如下一段:
//if(ans==64){
// cout<<18446744073709551615ull+1-n<<endl;
// return 0;
//}
unsigned long long ans1=(1ull<<ans)-n;
cout<<ans1<<endl;
如果ans是64的话,就会出错。但是如果用注释里面的代码特判一下ans是64的情况,就可以AC,本地windows电脑试了都没问题。
怀疑是windows系统和linux系统不一样导致的,回到家用苹果试了一下如下的程序:
#include <iostream>
using namespace std;
typedef unsigned long long ull;
int main(){
cout<<(1ull<<64ull)-1<<endl;
cout<<(1ull<<64)-1<<endl;
cout<<(1ull<<63)*2-1<<endl;
cout<<0ull-1<<endl;
cout<<(1ull<<63ull)-1<<endl;
cout<<(1ull<<63)-1<<endl;
return 0;
}
输出结果是:
140732682357592
73896
18446744073709551615
18446744073709551615
9223372036854775807
9223372036854775807
结合在网上查的资料,可以大概确定几个事情。
左移位运算,如果移位的位数超过或者等于类型本身的位数,行为是未定义的,在不同系统上,结果可能不一样。比如前两个例子里面,因为unsigned long long类型的长度是64位,所以左移64位的答案,变得非常诡异。
但是左移63位,再乘以2,就会得到正确的
其实用0表示