C#には、これを素朴に処理するのに十分な浮動精度と範囲のデータ型があるとは思いません。
本当にこのパスをたどりたい場合は、共役
が1未満であることに気付くことができます。これ
は、最も近い整数に丸めるのと同じことです。したがって、を見つけるためのソリューションを単純化できます
。次に、二項展開を使用して
、適切なaとb(有理数であり、BigIntegerで正確に計算できる)を使用して、を計算するだけで済みます。それでもこのためにDoubleに戻ると、1475を超えることはありませんが、正確な整数演算だけでこの部分を実行する方法を理解できるはずです☺</ p>

行列指数を使用してフィボナッチ数を計算するためのもう1つの優れた方法があります。

あなたが賢いなら、これはO(log n)で行うことができます。
私はこれらをHaskellに実装することになりました。 fib1
は行列指数でありfib2
、上記のように閉形式の式の正確な整数変換です。GHC 7.0.3でコンパイルしたときにCriterionで測定すると、それぞれのランタイムは次のようになります。
import Control.Arrow
import Data.List
import Data.Ratio
newtype Matrix2 a = Matrix2 (a, a, a, a) deriving (Show, Eq)
instance (Num a) => Num (Matrix2 a) where
Matrix2 (a, b, c, d) * Matrix2 (e, f, g, h) =
Matrix2 (a*e+b*g, a*f+b*h, c*e+d*g, c*f+d*h)
fromInteger x = let y = fromInteger x in Matrix2 (y, 0, 0, y)
fib1 n = let Matrix2 (_, x, _, _) = Matrix2 (1, 1, 1, 0) ^ n in x
binom n =
scanl (\a (b, c)-> a*b `div` c) 1 $
takeWhile ((/=) 0 . fst) $ iterate (pred *** succ) (n, 1)
evens (x:_:xs) = x : evens xs
evens xs = xs
odds (_:x:xs) = x : odds xs
odds _ = []
iterate' f x = x : (iterate' f $! f x)
powers b = iterate' (b *) 1
esqrt e n = x where
(_, x):_ = dropWhile ((<=) e . abs . uncurry (-)) $ zip trials (tail trials)
trials = iterate (\x -> (x + n / x) / 2) n
fib' n = (a, b) where
d = 2 ^ n
a = sum (zipWith (*) (odds $ binom n) (powers 5)) % d
b = sum (zipWith (*) (evens $ binom n) (powers 5)) % d
fib2 n = numerator r `div` denominator r where
(a, b) = fib' n
l = lcm (denominator a) (denominator a)
r = a + esqrt (1 % max 3 l) (b * b / 5) + 1 % 2