为什么下面的代码没有给出预期的输出,即使它适用于一些小输入?在这里,我期待" a"之间范围内所有整数的总和。和" b"。逻辑是错误还是其他一些错误?
class RangeSum {
public static void main(String args[] ){
// BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
long i = Long.valueOf("99");
long j = Long.valueOf("1000000000000");
long ans = 0L;
/*if(i<0 || i>Math.pow(10, 18)){
//throw new Exception("Wroong Input.");
}
if(i<0 || i>Math.pow(10, 18)){
//throw new Exception("Wroong Input.");
}*/
if (j>i){
long sumTill_j = (j*(j+1))/2;
long sumTill_i = ((i-1)*i)/2;
ans = sumTill_j - sumTill_i;
System.out.println(ans);
}else{
long sumTill_i = (i*(i+1))/2;
long sumTill_j = ((j-1)*j)/2;
ans = sumTill_i - sumTill_j;
System.out.println(ans);
}
}
}
答案 0 :(得分:5)
long
中可以表示的最大可能数字是2 63 - 1,大约是9.2 x 10 18 。如果你的计算超过了那个,那么计算将溢出而不会抛出任何异常,你将得到错误的答案。
在你的情况下:
1,000,000,000,000 * (1,000,000,000,000 + 1) / 2
如果我的心算是正确的,约为5 x 10 23 。那会溢出。
解决方案:使用BigInteger
。
答案 1 :(得分:3)
这是integer overflow的结果。这意味着,即使您使用的是最大的原语(long
),您尝试计算的值也会超出最大可表示值。
long只能存储2 63 -1,which is around 9 quintillion或9.22 * 10 18 的值。您尝试从总和生成的值超过该值with a difference of around 499 sextillion.
不要担心;你仍然可以计算这个疯狂的大值,但你必须做一些改变,特别是你不能再使用long
。转而转到BigInteger
。
您不能使用任何原始运算符,但您可以调用您希望可用的函数,例如add
,subtract
,multiply
和{ {1}}。
这是转换为使用它的代码的第一部分;我将另一半作为练习留给读者。
divide
答案 2 :(得分:1)
1000000000000 = 0xE8D4A51000
需要至少40位才能存储。因此,将j
乘以j+1
需要存储80位类型。结果是溢出long
类型,因为它只有64位。如果你真的想这样做,唯一的方法是使用像BigInteger
顺便说一下为什么不使用99L
和1000000000000L
?调用valueOf
只是多余且缓慢的
long i = Long.valueOf("99");
long j = Long.valueOf("1000000000000");
答案 3 :(得分:0)
简而言之:j * (j + 1)
时j = 1,000,000,000,000
会溢出。
Java signed long有64位,最大值为2^63 - 1
或9,223,372,036,854,775,807
。
答案 4 :(得分:0)
您的整数值很高,请尝试使用其他类型的整数,因为它会帮助那些更大的值。这是一个很好的网站,详细解释了BigInteger:http://www.tutorialspoint.com/java/math/java_math_biginteger.htm