java中的内存错误

时间:2016-04-30 16:20:32

标签: java

我正在尝试编写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是什么都可以正常工作,我的问题是我无法发挥作用。

3 个答案:

答案 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。