我有这个用于计算某些数字的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=1
和b=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)?
答案 0 :(得分:5)
如果您使用int
进行计算,速度会快得多。但是,从每次迭代中只有1,000,000个a
和b
的可能起始值(这意味着a
和b
的最长可能值序列和结果),您将获得更快的速度。 n % 1,000,000
不重复是一百万。即你可以a
最有可能的是重复序列较短。
我只说b
和mod 1000
的低三位数的原因是你a
结果,所以无论b
的高位是什么, 0
被忽略,所以您关心的是值999
到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;
}
您可以记住从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);