Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的大数字计算?_Java_Long Integer_Biginteger - Fatal编程技术网

Java中的大数字计算?

Java中的大数字计算?,java,long-integer,biginteger,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 = BigIntege

我有这个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));
        }
    }
}
然后返回
b mod 1000
,给出计算的最后3位数字

到目前为止,代码返回:

1 ---> 2
2 ---> 5
5 ---> 783
10 ---> 968
20 ---> 351
9223372036854775807 ---> 
在最后一次迭代中,代码继续工作,但如果迭代次数太大,则需要花费很长时间,因此永远无法完成


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

这个数字太大了。处理这个函数需要很长时间是正常的。 您可以尝试使用以下方法进行检查:


long startTime=System.currentTimeMillis();
……你的节目。。。。
long-endTime=System.currentTimeMillis();
长总时间=结束时间-开始时间;
系统输出打印项次(总时间);


完成计算的估计时间。

是的,为每次计算保持运行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);
}

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

如果使用
int
进行计算,速度会快得多。但是,如果您意识到在每次迭代中,
a
b
只有1000000个可能的起始值,则速度会更快,这意味着
a
b
不重复的最长可能值序列和结果为一百万。i、 e.您可以
n%1000000
最有可能存在较短的重复序列

我之所以只说
a
b
的下三位数很重要,是因为你
mod 1000
结果,所以不管
a
b
的上三位数是什么,它们都会被忽略,所以你只关心
0
999

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

private 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;
}
专用静态长计算(长n){
INTA=1;
int b=1;
对于(int i=0,max=(int)(n%1000000);i
它真的需要在
Long.MAX\u值下工作吗?如果是这样的话,忘记
for
循环吧,你不可能循环9223372036854775807次。既然你最后在做
mod 1000
,你也可以放弃
biginger
,在每次迭代中都用1k修改整数。另外,您显然需要找到序列的周期。任何理智的人都不会要求你循环
Long.MAX\u VALUE
次。据我所知,我需要做的是迭代到
I
,而不是
I
,对吗?我改了,看起来效果不错,号码是512。虽然我仍然不完全理解为什么a和b只有1000000个可能的起始值。1000000是函数的周期吗?@Julian只有
a
b
的较低3位才重要。其中最长的可能序列包括1000*1000的每个可能组合。重复序列可能较短,但应为1000000倍。
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;
}
private 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;
}