Java中的大数字计算?

时间:2015-12-15 16:38:49

标签: java long-integer biginteger

我有这个用于计算某些数字的Java代码

import java.math.BigInteger;

class Challenge {

    final static BigInteger THOUSAND = new BigInteger("1000");

    private static BigInteger compute(long n) {
        BigInteger a = BigInteger.ONE;
        BigInteger b = BigInteger.ONE;
        for (long i = 0; i < n; i++) {
            BigInteger next = b.multiply(b).add(a);
            a = b;
            b = next;
        }
        return b.mod(THOUSAND);
    }

    public static void main(String args[]) {
        for (long n : new long[] { 1L, 2L, 5L, 10L, 20L, Long.MAX_VALUE }) {
            System.out.print(n + " ---> ");
            System.out.println(compute(n));
        }
    }
}

代码根据给定的长数字(1,2,5等)迭代几次,从a=1b=1开始:

next = (b*b)+a
a = b
b = next

然后返回b mod 1000,它给出了计算的最后3位数。

到目前为止,代码返回:

1 ---> 2
2 ---> 5
5 ---> 783
10 ---> 968
20 ---> 351
9223372036854775807 ---> 

在最后一个代码中,代码保持工作,但是如果迭代次数太大则需要永久工作,因此它永远不会完成。

有没有办法更快地进行这种计算,或者以更好的方式获得所需的值(多次计算的mod 1000)?

3 个答案:

答案 0 :(得分:5)

如果您使用int进行计算,速度会快得多。但是,从每次迭代中只有1,000,000个ab的可能起始值(这意味着ab的最长可能值序列和结果),您将获得更快的速度。 n % 1,000,000不重复是一百万。即你可以a最有可能的是重复序列较短。

我只说bmod 1000的低三位数的原因是你a结果,所以无论b的高位是什么, 0被忽略,所以您关心的是值999private static long compute(long n) { int a = 1; int b = 1; for (int i = 0, max = (int) (n % 1000000); i < max; i++) { int next = b * b + a; a = b; b = next % 1000; } return b % 1000; }

您可以记住从1,1开始的所有可能结果,它只是一个查找。

       // Simple GET request example:
        $http({
          method: 'GET',
          url: 'http://user1:pass1@url/redmine/issues.xml'
        }).then(function successCallback(response) { 
            console.log("SUCCESS");
          }, function errorCallback(response) {
            console.log("ERROR");
          });

答案 1 :(得分:4)

是的,保持每次计算的运行moludo。您不需要计算所有数字,因为您只对最后3个数字感兴趣。

第一个改进是拥有以下内容:

private static BigInteger compute(long n) {
    BigInteger a = BigInteger.ONE;
    BigInteger b = BigInteger.ONE;
    for (long i = 0; i < n; i++) {
        BigInteger next = b.multiply(b).add(a);
        a = b;
        b = next.mod(THOUSAND); // <-- only keep the modulo each time so as not calculate all digits
    }
    return b.mod(THOUSAND);
}

通过这样做,您可以意识到您不需要BigInteger开始。有关的数字变得足够低,以至于它们保持原始数据类型。因此,请使用long(甚至是int):因为您没有使用BigInteger的开销,所以性能会更高。

private static long compute(long n) {
    int a = 1;
    int b = 1;
    for (long i = 0; i < n; i++) {
        int next = b*b + a;
        a = b;
        b = next % 1000;
    }
    return b % 1000;
}

请注意,此代码仍然无法为9223372036854775807输入结果。根本不可能循环9223372036854775807次。但是,这会在我的旧机器上在5秒内产生1亿的正确结果。

答案 2 :(得分:-3)

这个数字很大。处理此功能花了这么长时间是正常的。 您可以尝试使用以下方法进行检查:

long startTime = System.currentTimeMillis(); .....your program.... long endTime = System.currentTimeMillis(); long totalTime = endTime - startTime; System.out.println(totalTime);

估计完成它的时间。