O(log n)でフィボナッチ数を求める
O(log n)でフィボナッチ数のN番目を求める方法をRubyで実装してみました。この間のSICP勉強会で教えてもらったやつです。
まず普通のフィボナッチ数。こいつはO(n)です。
def fib1(n) a, b = 0, 1 n.times do a, b = a + b, a end a end
O(log n)版のフィボナッチ数。なんでこれでフィボナッチ数が求められるかは、ここを参照してください。ちなみにRubyのMatrixの**は、O(log n)で実装されています。
require 'matrix' def fib2(n) a = Matrix[[1, 1], [1, 0]] b = Matrix[[0], [1]] (a ** n * b)[0, 0] end
こんな感じでベンチマークをとってみました。
require 'benchmark' n = 100_000 Benchmark.bm do |x| x.report("fib1(#{n}):") { fib1(n) } x.report("fib2(#{n}):") { fib2(n) } end
user system total real fib1(100000): 2.653000 0.370000 3.023000 ( 3.284000) fib2(100000): 0.391000 0.000000 0.391000 ( 0.391000)
んー、10万くらいだとオーダーの差を感じられますね。