“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 - 19,223,372,036,854,775,807

1000000000000 = 0xE8D4A51000 至少需要 40 位来存储。因此 j 乘以 j+1 需要一个 80 位的类型来存储。结果溢出 long 类型,因为它只有 64 位。如果你真的想这样做,唯一的方法就是使用像 BigInteger

这样的 bigint 类型

顺便说一句,为什么不直接使用 99L1000000000000L?调用 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

您不能改用任何原始运算符,但可以调用您希望可用的函数,例如 addsubtractmultiply、和 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);
}

您的整数值过高。尝试改用另一种类型的整数,因为它会帮助那些更大的值。这是一个很好的网站,详细解释了 BigIntegerhttp://www.tutorialspoint.com/java/math/java_math_biginteger.htm