“a”到“b”之间的整数之和对于大输入给出错误的结果
Sum of integers ranging between “a” to “b” gives wrong result for large inputs
为什么以下代码没有给出预期的输出,即使它适用于一些小的输入?在这里,我期望 "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);
}
}
}
您可以在 long
中表示的最大可能数字是 263 - 1,大约是 9.2 x 1018。如果您的计算超出了这个范围,那么计算将溢出 而不会抛出任何异常 ,您将得到错误的答案。
你的情况:
1,000,000,000,000 * (1,000,000,000,000 + 1) / 2
如果我的心算正确的话,大约是 5 x 1023。那会溢出的。
解决方法:使用BigInteger
.
简而言之:j * (j + 1)
在 j = 1,000,000,000,000
时溢出。
Java的signed long有64位,最大值为2^63 - 1
或9,223,372,036,854,775,807
。
1000000000000 = 0xE8D4A51000
至少需要 40 位来存储。因此 j
乘以 j+1
需要一个 80 位的类型来存储。结果溢出 long
类型,因为它只有 64 位。如果你真的想这样做,唯一的方法就是使用像 BigInteger
这样的 bigint 类型
顺便说一句,为什么不直接使用 99L
和 1000000000000L
?调用 valueOf
是多余的而且很慢
long i = Long.valueOf("99");
long j = Long.valueOf("1000000000000");
这是integer overflow的结果。这意味着,即使您使用了最大的基元 (long
),您尝试计算的值也超过了最大可表示值。
一个long只能存储一个值为263-1,which is around 9 quintillion, or 9.22 * 1018. The value that you're trying to generate from your sum exceeds that value with a difference of around 499 sextillion.
别担心;你仍然可以计算出这个非常大的值,但是你必须做一些改变,特别是你不能再使用 long
。改为 BigInteger
。
您不能改用任何原始运算符,但可以调用您希望可用的函数,例如 add
、subtract
、multiply
、和 divide
.
这里是转换使用它的第一部分代码;我将另一半留作 reader.
的练习
BigInteger i = BigInteger.valueOf(99L);
BigInteger j = BigInteger.valueOf(1000000000000L);
BigInteger ans = BigInteger.ZERO;
if (j.compareTo(i) > 0) {
BigInteger sumTill_j = (j.multiply(j.add(BigInteger.ONE))).divide(BigInteger.valueOf(2L));
BigInteger sumTill_i = ((i.subtract(BigInteger.ONE)).multiply(i)).divide(BigInteger.valueOf(2L));
ans = sumTill_j.subtract(sumTill_i);
System.out.println(ans);
}
您的整数值过高。尝试改用另一种类型的整数,因为它会帮助那些更大的值。这是一个很好的网站,详细解释了 BigInteger
:http://www.tutorialspoint.com/java/math/java_math_biginteger.htm
为什么以下代码没有给出预期的输出,即使它适用于一些小的输入?在这里,我期望 "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);
}
}
}
您可以在 long
中表示的最大可能数字是 263 - 1,大约是 9.2 x 1018。如果您的计算超出了这个范围,那么计算将溢出 而不会抛出任何异常 ,您将得到错误的答案。
你的情况:
1,000,000,000,000 * (1,000,000,000,000 + 1) / 2
如果我的心算正确的话,大约是 5 x 1023。那会溢出的。
解决方法:使用BigInteger
.
简而言之:j * (j + 1)
在 j = 1,000,000,000,000
时溢出。
Java的signed long有64位,最大值为2^63 - 1
或9,223,372,036,854,775,807
。
1000000000000 = 0xE8D4A51000
至少需要 40 位来存储。因此 j
乘以 j+1
需要一个 80 位的类型来存储。结果溢出 long
类型,因为它只有 64 位。如果你真的想这样做,唯一的方法就是使用像 BigInteger
顺便说一句,为什么不直接使用 99L
和 1000000000000L
?调用 valueOf
是多余的而且很慢
long i = Long.valueOf("99");
long j = Long.valueOf("1000000000000");
这是integer overflow的结果。这意味着,即使您使用了最大的基元 (long
),您尝试计算的值也超过了最大可表示值。
一个long只能存储一个值为263-1,which is around 9 quintillion, or 9.22 * 1018. The value that you're trying to generate from your sum exceeds that value with a difference of around 499 sextillion.
别担心;你仍然可以计算出这个非常大的值,但是你必须做一些改变,特别是你不能再使用 long
。改为 BigInteger
。
您不能改用任何原始运算符,但可以调用您希望可用的函数,例如 add
、subtract
、multiply
、和 divide
.
这里是转换使用它的第一部分代码;我将另一半留作 reader.
的练习BigInteger i = BigInteger.valueOf(99L);
BigInteger j = BigInteger.valueOf(1000000000000L);
BigInteger ans = BigInteger.ZERO;
if (j.compareTo(i) > 0) {
BigInteger sumTill_j = (j.multiply(j.add(BigInteger.ONE))).divide(BigInteger.valueOf(2L));
BigInteger sumTill_i = ((i.subtract(BigInteger.ONE)).multiply(i)).divide(BigInteger.valueOf(2L));
ans = sumTill_j.subtract(sumTill_i);
System.out.println(ans);
}
您的整数值过高。尝试改用另一种类型的整数,因为它会帮助那些更大的值。这是一个很好的网站,详细解释了 BigInteger
:http://www.tutorialspoint.com/java/math/java_math_biginteger.htm