Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.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
计算斐波那契序列第n项的最快Java算法?_Java_Fibonacci - Fatal编程技术网

计算斐波那契序列第n项的最快Java算法?

计算斐波那契序列第n项的最快Java算法?,java,fibonacci,Java,Fibonacci,知道计算斐波那契序列第n项的最快Java算法是什么吗 我找到了。我想迭代算法应该比递归和解析算法更快 试试看。创建一个数组,该数组保存第n-1个斐波那契数的每个值。第一次运行时,它将花费与普通斐波那契函数一样长的时间,但后续调用可以在O(1)中运行,因为您已经在数组中拥有了值。根据我的经验,分析版本在实践中通常非常快,但正如Rosetta代码所指出的,它只能精确到序列中的第92个数字 递归版本需要指数级的运行时间,因此即使对于中等大小的n,它也必然非常慢。迭代和尾部递归函数的时间以n为单位呈线性

知道计算斐波那契序列第n项的最快Java算法是什么吗


我找到了。我想迭代算法应该比递归和解析算法更快

试试看。创建一个数组,该数组保存第n-1个斐波那契数的每个值。第一次运行时,它将花费与普通斐波那契函数一样长的时间,但后续调用可以在O(1)中运行,因为您已经在数组中拥有了值。

根据我的经验,分析版本在实践中通常非常快,但正如Rosetta代码所指出的,它只能精确到序列中的第92个数字

递归版本需要指数级的运行时间,因此即使对于中等大小的n,它也必然非常慢。迭代和尾部递归函数的时间以n为单位呈线性。从斐波那契序列的性质出发,可以导出一种更快的O(lgn)时间算法

有关递归和尾部递归算法的解释,请参见SICP。

答案通常是“视情况而定”。一般来说,你无法真正存储那么多的斐波那契数,因为它们的增长速度相当快——事实上,正如你链接的分析部分所揭示的那样呈指数增长

因此,对于大多数实际用途,答案是“不要计算——缓存”。也就是说,使用查找表。(无论如何,在溢出之前,通常需要少于100个条目。)

对于传统的存储方法,你不会比递归计算做得更好,因为它是O(d^2),其中d是输出的位数——更复杂的任意大小的数字操作将很难与之竞争


“分析”可能是较慢的方法之一,因为基数不方便,而且你会丢掉快速整数数学。

预先计算所有的斐波那契数,直到n足够大,并生成一个源代码片段,定义一个数组,该数组的数字类型可以容纳这些数字


然后您可以在数组中的index
n
中检索值。这是
O(1)
。没有比这更快的了。

当您特别针对Java时,我昨晚在Python3中看到了不同的实现。特别是,我研究了朴素的递归实现和分析实现(不过我称之为闭式实现)。以下是代码,无需我的单元测试:

import math
from timeit import Timer

def fib_recursive(n):
    """
        Compute the Fibonacci sequence from a given number n
    """
    if n < 2:
        return n
    else:
        return fib_recursive(n - 2) + fib_recursive(n - 1)

def fib_closed_form(n):
    """
        Compute the Fibonacci sequence using a closed form.
    """
    def calc_golden_ratio():
        return (1 + math.sqrt(5)) / 2

    gr = calc_golden_ratio()
    inverse_gr = 1 - gr
    numerator = math.pow(gr,  n) - math.pow(inverse_gr,  n)
    return numerator // math.sqrt(5)

if __name__ == '__main__':
    for n in range(0,  10):
        n = str(n)
        time = Timer("fib_closed_form(" + n + ")",  "from __main__ import fib_closed_form")
        print('Fib_Closed_Form(' + n +') = ' + str(time.timeit()))
        time = Timer("fib_recursive(" + n + ")",  "from __main__ import fib_recursive")
        print('Fib_Recursive(' + n +') = ' + str(time.timeit()))
正如您所看到的,这种封闭形式具有更高的前期成本。递归的那个把它从水里吹出来!不过,它只有在n=4时才能保持竞争力。但是你可以看到它的时机变得越来越糟糕。当我们达到n=6时,我们已经看到这不是正确的方向

顺便说一下,我昨晚尝试了n=25。闭式表单花费的时间大致相同,递归表单在我睡觉前(至少运行了半个小时)没有完成


我的观点是,这些测试非常容易实现,并且可以直接为其提供一些单元测试。您可以试一试,自己在Java中查看结果,尽管在Java等语言中计时可能很复杂,无需额外设置。

您可以测试它!(你只需要知道你自己的计算机架构)不幸的是,这不是一个讨论板。一个合适的问题是“我试过分析这些算法,但不明白为什么会得到这个结果”。@talnicolas这些算法只是例子……我想问的是,是否有人知道哪种算法最快……评论仍然适用。这类问题属于@JimGarrison,谢谢链接……可能吧。不过,我已经删除了我答案中的这一部分;事实上,它将以正常斐波那契函数的相同顺序运行,但对于斐波那契值,如果预先计算逆函数,时间会如何变化?这是个好问题。我没有计时,但我想只是稍微好一点,因为不必使用嵌套函数/调用sqrt。不过,这只是一点点,它只会把常数因子去掉。总的来说,它的性能与规模保持一致。。如果你不想预先计算。当然,预先计算对我来说要快得多。在我的I-7上,只要不让它耗尽内存,BigInteger系列在达到45000时每千个数字需要60秒。我还预先将ArrayList分配到200000,但要运行那么长的时间还需要一段时间
Python 3.2.2 (default, Nov 21 2011, 16:50:59) 
[GCC 4.6.2] on staggerlee, Standard
>>> 
Fib_Closed_Form(1) = 5.808775901794434
Fib_Recursive(1) = 0.6938691139221191

Fib_Closed_Form(2) = 6.142783880233765
Fib_Recursive(2) = 1.9276459217071533

Fib_Closed_Form(3) = 6.62189793586731
Fib_Recursive(3) = 3.6403379440307617

Fib_Closed_Form(4) = 6.376585960388184
Fib_Recursive(4) = 6.733421802520752

Fib_Closed_Form(5) = 6.566863059997559
Fib_Recursive(5) = 11.409136056900024

Fib_Closed_Form(6) = 6.521269083023071
Fib_Recursive(6) = 18.514809131622314

...

Fib_Closed_Form(10) = 6.631903886795044
Fib_Recursive(10) = 131.51839208602905