我最近对算法产生了兴趣,由于其简单性,斐波纳契序列引起了我的注意.
我已经设法将一些东西放在javascript中,在网上阅读大量信息后,在不到15毫秒的时间内计算出斐波那契序列中的第n个项.它上升到1476 ... 1477是无穷大,1478是NaN(根据javascript!)
我为代码本身感到自豪,除了它是一个彻头彻尾的怪物.
所以这是我的问题:A)有更快的方法来计算序列吗?B)是否有更快/更小的方法来乘以两个矩阵?
这是代码:
//Fibonacci sequence generator in JS //Cobbled together by Salty m = [[1,0],[0,1]]; odd = [[1,1],[1,0]]; function matrix(a,b) { /* Matrix multiplication Strassen Algorithm Only works with 2x2 matrices. */ c=[[0,0],[0,0]]; c[0][0]=(a[0][0]*b[0][0])+(a[0][1]*b[1][0]); c[0][1]=(a[0][0]*b[0][1])+(a[0][1]*b[1][1]); c[1][0]=(a[1][0]*b[0][0])+(a[1][1]*b[1][0]); c[1][1]=(a[1][0]*b[0][1])+(a[1][1]*b[1][1]); m1=(a[0][0]+a[1][1])*(b[0][0]+b[1][1]); m2=(a[1][0]+a[1][1])*b[0][0]; m3=a[0][0]*(b[0][1]-b[1][1]); m4=a[1][1]*(b[1][0]-b[0][0]); m5=(a[0][0]+a[0][1])*b[1][1]; m6=(a[1][0]-a[0][0])*(b[0][0]+b[0][1]); m7=(a[0][1]-a[1][1])*(b[1][0]+b[1][1]); c[0][0]=m1+m4-m5+m7; c[0][1]=m3+m5; c[1][0]=m2+m4; c[1][1]=m1-m2+m3+m6; return c; } function fib(n) { mat(n-1); return m[0][0]; } function mat(n) { if(n > 1) { mat(n/2); m = matrix(m,m); } m = (n%2<1) ? m : matrix(m,odd); } alert(fib(1476)); //Alerts 1.3069892237633993e+308
矩阵函数有两个参数:a和b,并返回a*b,其中a和b是2x2数组.哦,并且在旁注中,发生了一件神奇的事情......我正在将Strassen算法转换为JS数组表示法,并且它在我第一次尝试时起作用了!太棒了,对吧?:P
如果您设法找到一种更简单的方法,请提前致谢.
不要推测,基准:
编辑:我使用我的其他答案中提到的优化乘法函数添加了我自己的矩阵实现.这导致了主要的加速,但即使是带有循环的矩阵乘法的vanilla O(n ^ 3)实现也比Strassen算法快.
产量
fib.round(1450) = 4.8149675025003456e+302 [20ms] fib.loop(1450) = 4.81496750250011e+302 [4035ms] fib.loop_cached(1450) = 4.81496750250011e+302 [8ms] fib.matrix(1450) = 4.814967502500118e+302 [2201ms] fib.matrix_optimised(1450) = 4.814967502500113e+302 [585ms] fib.matrix_cached(1450) = 4.814967502500113e+302 [12ms]
您的算法几乎与未缓存的循环一样糟糕.缓存是你最好的选择,紧接着是舍入算法 - 这会产生大的错误结果n
(就像你的矩阵算法一样).
对于较小的n
,您的算法执行甚至比其他一切更糟糕:
fib.round(100) = 354224848179263100000 [20ms] fib.loop(100) = 354224848179262000000 [248ms] fib.loop_cached(100) = 354224848179262000000 [6ms] fib.matrix(100) = 354224848179261900000 [1911ms] fib.matrix_optimised(100) = 354224848179261900000 [380ms] fib.matrix_cached(100) = 354224848179261900000 [12ms]
对于第n个Fibonacci数,存在闭合形式(无循环)解.
见维基百科.