我正在解决一个编程问题(Leetcode上的问题633)。
下面的代码没有运行,它给出了这个错误:
运行时错误:有符号整数溢出:829921 + 2146654224 无法用类型"int"表示
bool judgeSquareSum(int c)
{
int h=sqrt(c),l=0;
while(l<=h)
{
long long sum=l*l+h*h;
if(sum>c)
{
h--;
}
else
if(sum<c)
l++;
else
return true;
}
return false;
}
而下面的代码运行完美。唯一的区别是,与上述代码中的变量类型相比int
变量l
和h
属于long long
类型。
要指定 -l
和h
的值不能大于INT_MAX
l*l
和h*h
都不能大于INT_MAX
。
bool judgeSquareSum(int c) {
long long l = 0, h = sqrt(c);
while (h >= l) {
long long xxxx = l * l + h * h;
if (xxxx > c) {
h--;
} else if (xxxx < c) {
l++;
} else {
return true;
}
}
return false;
}
错误消息准确地告诉您问题所在:
有符号整数溢出:829921 + 2146654224不能用类型"int"表示
您正在尝试829921和2146654224添加值,结果(应2147484145)不适合int
。 这告诉我们,您几乎可以肯定是在一台INT_MAX
为 231-1或 2147483647 的机器上运行
的这似乎来自生产线
long long xxxx = l * l + h * h;
其中l
和h
都具有类型int
,因此表达式l * l + h * h
将被计算为类型int
。 该值将用于初始化类型long long
的值这一事实无关紧要 - 在 C(和 C++)中,表达式的类型和精度仅由操作数的类型决定,而不是由结果的使用方式决定。
您可以通过谨慎操作来避免溢出。 由于您知道c
适合 int 和h
并且l
总是 <= sqrt(c),所以h * h
和l * l
不会溢出,所以溢出的只是总和。 因此,您可以将代码重写为:
bool judgeSquareSum(int c) {
int l = 0, h = sqrt(c);
while (h >= l) {
int xxxx = l * l - c + h * h;
if (xxxx > 0) {
h--;
} else if (xxxx < 0) {
l++;
} else {
return true;
}
}
return false;
}
并且不需要更大的类型
long long
的大小至少为 64 位。int
的大小至少为 16 位。因此,并非所有可以用long long
表示的数字也可以表示为没有值损失的int
,因此需要更大的类型。在此处查看更多内容: https://en.cppreference.com/w/cpp/language/types