我想编写一个程序来计算由n行组成的区域数。 第一个例子是我的代码,第二个例子是我朋友的代码。我认为他们正在尝试做同样的事情,但对于n = 65535的情况,我的代码给了我错误的答案。我的代码中的问题在哪里?
我的代码:
#include<iostream>
using namespace std;
int main()
{
int n;
cin >> n;
unsigned long long ans;
ans = (n*(n + 1) / 2) + 1;
cout << ans << endl;
return 0;
}
我朋友的代码:
#include <iostream>
using namespace std;
int main(void){
double n,sum;
cin>>n;
sum=n*(n+1)/2+1;
cout<<(long)sum<<endl;
return 0;
}
答案 0 :(得分:4)
在您的代码中:
int n;
ans = (n*(n + 1) / 2) + 1;
计算中的所有值都是整数:n
声明为int,普通整数常量也是整数。因此,此计算的结果也将是int。您稍后将此结果分配给long long变量的事实不会改变这一点。
现在乘法65535 * 65536的结果不适合32位有符号int,所以你得到一个无意义的答案。通过使n
长64位来修复程序。
答案 1 :(得分:4)
正如@Dithermaster建议的那样,这里的问题可能是整数溢出。
现在看来,你的代码实际上没有多大意义。特别是,由于您已将n
定义为int
,并且表达式中的所有整数文字:(n*(n + 1) / 2) + 1
也足够小以适合int
,计算将在int
s上进行,然后(在计算完成后),结果将转换为long long
并分配给ans
(因为您已将ans
定义为long long
)。
您几乎肯定想要的是在long long
上执行整个计算以避免溢出。最明显的方法是将n
定义为long long
而不是int
。
您的朋友通过将n
定义为double
来避免这种情况。这一点起作用 - double
的典型实现具有53位有效数,因此它可以(基本上)用作53位整数类型。这显然比int
强制要求的16位要多得多,但同样明显低于long long
规定的64位。
支持n
为否定也没有意义,因此您可以考虑将n
和ans
定义为unsigned long long
。