我正在尝试编写java素数算法。我试图用整数和长尺寸来解决问题。我的简单代码如下所示,直到n:
的限制为止public static long f(int n) {
if (n == 1 || n == 2)
return 1;
else {
long value = f(n-2) + f(n-1);
return value;
}
}
如果在我的主要内容中我将给出50例,我的代码将被粉碎,我猜是因为结果的大小。我还有另一种方法,我很难理解它,其中包括:
private static long[] cache = new long[60];
public static long f(int n) {
if (n == 1 || n == 2)
return 1;
else if (cache[n] > 0)
return cache[n];
else {
long value = f(n-2) + f(n-1);
cache[n] = value;
return value;
}
}
通过这种方法,无论n是什么都可以正常工作,我的问题是我无法发挥作用。
答案 0 :(得分:4)
“粉碎”你的意思是计算运行的时间非常长。原因是多次进行相同的呼叫。如果将其添加到方法中:
static long count;
public static long f(int n) {
count++;
...
您将看到该方法执行的次数。对于f(50)
,它实际上调用方法 25,172,538,049次,在我的机器上运行41秒。
当您缓存以前调用的结果(称为memoization)时,您将消除所有冗余调用,例如f(40) = f(39) + f(38)
,但f(39) = f(38) + f(37)
,因此f(38)
被调用两次。记住f(38)
的结果意味着后续调用会立即得到答案,而不必重做递归。
没有记忆,我明白了:
n f(n) count time(ns)
== ============== =============== ==============
1 1 1 6,273
2 1 1 571
3 2 3 855
4 3 5 1,141
5 5 9 1,425
6 8 15 1,140
7 13 25 1,996
8 21 41 2,851
9 34 67 7,413
10 55 109 16,536
11 89 177 8,839
12 144 287 19,103
13 233 465 21,098
14 377 753 11,405
15 610 1,219 5,703
16 987 1,973 9,979
17 1,597 3,193 21,099
18 2,584 5,167 32,788
19 4,181 8,361 35,639
20 6,765 13,529 57,307
21 10,946 21,891 91,521
22 17,711 35,421 147,687
23 28,657 57,313 237,496
24 46,368 92,735 283,970
25 75,025 150,049 331,583
26 121,393 242,785 401,720
27 196,418 392,835 650,052
28 317,811 635,621 1,053,483
29 514,229 1,028,457 1,702,679
30 832,040 1,664,079 2,750,745
31 1,346,269 2,692,537 4,455,137
32 2,178,309 4,356,617 12,706,520
33 3,524,578 7,049,155 11,714,051
34 5,702,887 11,405,773 19,571,980
35 9,227,465 18,454,929 30,605,757
36 14,930,352 29,860,703 51,298,507
37 24,157,817 48,315,633 84,473,965
38 39,088,169 78,176,337 127,818,746
39 63,245,986 126,491,971 208,727,118
40 102,334,155 204,668,309 336,785,071
41 165,580,141 331,160,281 543,006,638
42 267,914,296 535,828,591 875,782,771
43 433,494,437 866,988,873 1,429,555,753
44 701,408,733 1,402,817,465 2,301,577,345
45 1,134,903,170 2,269,806,339 3,724,691,882
46 1,836,311,903 3,672,623,805 6,010,675,962
47 2,971,215,073 5,942,430,145 9,706,561,705
48 4,807,526,976 9,615,053,951 15,715,064,841
49 7,778,742,049 15,557,484,097 25,427,015,418
50 12,586,269,025 25,172,538,049 41,126,559,697
答案 1 :(得分:2)
如果得到StackOverflowError,则归因于算法的递归性质。第二种算法将已知结果存储到数组中,以防止函数在询问已计算的结果时堆积起来。
答案 2 :(得分:-1)
其中一个问题可能是大数结果,超过整数限制:
斐波那契50 =
12,586,269,025
2,147,483,647 - int max
另一个可能是由于@Xalamadrax指向的递归stackoverflow。