Fibonacci matrix-exponentiation: Difference between revisions

m
(→‎{{header|Go}}: Updated all 3 versions in line with latest task changes.)
m (→‎{{header|Wren}}: Minor tidy)
 
(34 intermediate revisions by 10 users not shown)
Line 1:
{{draft task|Matrices}}[[Category:Mathematics]]
[[Category:Mathematics]]
 
The '''Fibonacci sequence''' defined with [[wp:Fibonacci_number#Matrix_form|matrix-exponentiation]]:
::::: <math>\begin{pmatrix} 1 & 1 \\ 1 & 0 \end{pmatrix}^n = \begin{pmatrix} F_{n+1} & F_n \\ F_n & F_{n-1} \end{pmatrix}.</math>
 
 
;Task:
Write a program using &nbsp; ''matrix exponentiation'' &nbsp; to generate Fibonacci(n) for &nbsp; '''n''' &nbsp; equal to: 10, 100, 1_000, 10_000, 100_000, 1_000_000 and 10_000_000.
:::* &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 10
:::* &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 100
:::* &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1,000
:::* &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 10,000
:::* &nbsp; &nbsp; &nbsp; &nbsp; 100,000
:::* &nbsp;&nbsp; &nbsp; 1,000,000
:::* &nbsp;&nbsp; 10,000,000
 
 
Display only the 20 first digits and 20 last digits of each Fibonacci number.
Only display the first '''20''' decimal digits &nbsp; and &nbsp; the last '''20''' decimal digits of each Fibonacci number.
 
;Extra:
Generate Fibonacci(2<sup>16 </sup>), Fibonacci(2<sup>32</sup>) and Fibonacci(2<sup>64</sup>) using the same method or another one.
 
 
;Related tasks:
* &nbsp; [[Fibonacci sequence]]
* &nbsp; [[Matrix-exponentiation operator]]
<br><br>
 
=={{header|C sharp|C#}}==
===Matrix exponentiation===
<langsyntaxhighlight lang="csharp">using System;
using System.IO;
using System.Numerics;
Line 35 ⟶ 48:
throw new ArgumentException("Illegal matrix dimensions for multiplication.");
}
var C = new BigInteger[A.GetLength(10), B.GetLength(01)];
for (int i = 0; i < A.GetLength(0); ++i)
{
for (int j = 0; j < B.GetLength(1); ++j)
{
for (int k = 0; k < BA.GetLength(01); ++k)
{
C[i, j] += A[i, k] * B[k, j];
Line 111 ⟶ 124:
}
 
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 130 ⟶ 143:
I have not attempted to calculate the (2^64)th Fibonacci number which appears to be well out of reach using this approach.
{{libheader|GMP(Go wrapper)}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 263 ⟶ 276:
 
fmt.Printf("Took %s\n\n", time.Since(start))
}</langsyntaxhighlight>
 
{{out}}
Line 310 ⟶ 323:
<br>
{{trans|Julia}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 406 ⟶ 419:
 
fmt.Printf("Took %s\n\n", time.Since(start))
}</langsyntaxhighlight>
 
{{out}}
Line 420 ⟶ 433:
{{trans|Sidef}}
{{trans|Julia}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 551 ⟶ 564:
s1 := firstFibDigits(n, nd2)
if len(s1) < 20 {
fmt.Printf(" All %-2d : %s\n", len(s1), s1)
} else {
fmt.Printf(" First 20 : %s\n", s1)
Line 574 ⟶ 587:
}
fmt.Printf("\nTook %s\n", time.Since(start))
}</langsyntaxhighlight>
 
{{out}}
<pre>
The digits of the 10th Fibonacci number are:
All 2 : 55
 
The digits of the 100th Fibonacci number are:
Line 622 ⟶ 635:
=={{header|Haskell}}==
===Matrix exponentiation===
<langsyntaxhighlight Haskelllang="haskell">import System.CPUTime (getCPUTime)
import Data.List
 
main = do
startTime <- getCPUTime
mapM_ (putStrLn.formatAns).take 7.iterate (*10) $ 10
mapM_ (putStrLn.seeFib) [16,32]
finishTime <- getCPUTime
putStrLn $ "Took " ++ (took startTime finishTime)
 
took t = fromChrono.chrono t
 
fromChrono :: (Integer,Integer,Integer) -> String
fromChrono (m,s,ms) = show m ++ "m" ++ show s ++ "." ++ show ms ++ "s"
 
chrono :: Integer -> Integer -> (Integer,Integer,Integer)
chrono start end = (m,s,ms)
where
tera = 1000000000000
fdt = fromIntegral (end - start) / tera
dt = floor fdt
(m,s) = quotRem dt 60
ms = round $ fromIntegral (round (fdt - (fromIntegral dt))*1000) / 1000
 
bagOf :: Int -> [a] -> [[a]]
bagOf _ [] = []
bagOf n xs = let (us,vs) = splitAt n xs in us : bagOf n vs
 
formatIntegral :: Show a => String -> a -> String
formatIntegral sep = reverse.intercalate sep.bagOf 3.reverse.show
formatAns :: Integer -> String
formatAns p = start ++ go x
where
start = "Fibonacci("++ (formatIntegral "_" p) ++ ") = "
x = fib p
tenPow20 = 10^20
tenPow40 = tenPow20^2
go u | u <= tenPow20 = show u
go u | u <= tenPow40 = let (us,vs) = splitAt 20 $ show u in us ++ " ... " ++ vs
go u = (take 20 $ show u) ++ " ... " ++ (show . rem u $ 10^20)
 
seeFib :: Integer -> String
Line 630 ⟶ 683:
x = fib (2^n)
xs = take 20 $ show x
 
fib :: Integer -> Integer
fib 0 = 0 -- this line is necessary because "something ^ 0" returns "fromInteger 1", which unfortunately
-- in our case is not our multiplicative identity (the identity matrix) but just a 1x1 matrix of 1
fib n = (last . head . unMat) (Mat [[1, 1], [1, 0]] ^ n)
 
mult :: Num a => [[a]] -> [[a]] -> [[a]]
mult uss vss = map ((\xs -> if null xs then [] else foldl1 (zipWith (+)) xs) . zipWith (flip (map . (*))) vss) uss
Line 649 ⟶ 702:
fromInteger n = Mat [[fromInteger n]]
abs = undefined
signum = undefined</syntaxhighlight>
 
main :: IO ()
main =
do
startTime <- getCPUTime
mapM_ (putStrLn.seeFib) [16,32]
finishTime <- getCPUTime
let diff = ceiling $ fromIntegral (finishTime - startTime) / 1000000000000
let (minute,second) = quotRem diff 60
putStrLn $ "Took: " ++ (show minute) ++ "min" ++ (show second) ++ "s"
</lang>
{{out}}
Timing is on Intel Core i5-4300U CPU, Windows 10 Professional, using GHCi Version 8.6.5:
<pre>
Fibonacci(10) = 55
Fibonacci(100) = 35422484817926191507 ... 5
Fibonacci(1_000) = 43466557686937456435 ... 76137795166849228875
Fibonacci(10_000) = 33644764876431783266 ... 66073310059947366875
Fibonacci(100_000) = 25974069347221724166 ... 49895374653428746875
Fibonacci(1_000_000) = 19532821287077577316 ... 68996526838242546875
Fibonacci(10_000_000) = 11298343782253997603 ... 86998673686380546875
Fibonacci(2^16) = 73199214460290552832 ... 97270190955307463227
Fibonacci(2^32) = 61999319689381859818 ... 39623735538208076347
Took: 5min31s5m20.1s
</pre>
===Matrix exponentiation - printing alternative ===
<langsyntaxhighlight Haskelllang="haskell">import System.CPUTime (getCPUTime)
import Data.List
 
main = do
phi :: Double
startTime <- getCPUTime
phi = (1 + sqrt 5)/2
mapM_ (putStrLn.formatAns).take 7.iterate (*10) $ 10
log10phi = logBase 10 phi
mapM_ (putStrLn.seeFib) [16,32]
halflog10five = (logBase 10 5)/2
finishTime <- getCPUTime
putStrLn $ "Took " ++ (took startTime finishTime)
 
took t = fromChrono.chrono t
 
fromChrono :: (Integer,Integer,Integer) -> String
fromChrono (m,s,ms) = show m ++ "m" ++ show s ++ "." ++ show ms ++ "s"
 
chrono :: Integer -> Integer -> (Integer,Integer,Integer)
chrono start end = (m,s,ms)
where
tera = 1000000000000
fdt = fromIntegral (end - start) / tera
dt = floor fdt
(m,s) = quotRem dt 60
ms = round $ fromIntegral (round (fdt - (fromIntegral dt))*1000) / 1000
 
bagOf :: Int -> [a] -> [[a]]
bagOf _ [] = []
bagOf n xs = let (us,vs) = splitAt n xs in us : bagOf n vs
 
formatIntegral :: Show a => String -> a -> String
formatIntegral sep = reverse.intercalate sep.bagOf 3.reverse.show
 
formatAns :: Integer -> String
formatAns p = start ++ (startEnd 20 (sizeFib p) num)
where
start = "Fibonacci("++ (formatIntegral "_" p) ++ ") = "
num = fib p
 
seeFib :: Integer -> String
seeFib n = start ++ xs(startEnd 20 (sizeFib p) num)
where
start = "Fibonacci(2^" ++ (show n) ++") = "
p = 2^n
xnum = fib p
fp = fromIntegral p
len = floor $ fp*log10phi - halflog10five
xs = if len <= 40 then (show x) else (show . quot x $ 10^(len-19)) ++ " ... " ++ (show . rem x $ 10^20)
 
startEnd :: (Integral a, Show a) => a -> a -> a -> String
startEnd ndigit len num | len <= ndigit = show num
startEnd ndigit len num | len <= 2*ndigit = let (us,vs) = genericSplitAt ndigit (show num) in us ++ " ... " ++ vs
startEnd ndigit len num = start ++ " ... " ++ end
where
end = show.rem num $ 10 ^ ndigit
start = show.quot num $ 10 ^ (len - ndigit + 1)
 
phi :: Double
phi = (1 + sqrt 5)/2
log10phi = logBase 10 phi
halflog10five =(logBase 10 5)/2
 
sizeFib :: Integral a => a -> a
sizeFib p = ceiling $ (fromIntegral p)*log10phi - halflog10five
fib :: Integer -> Integer
fib 0 = 0 -- this line is necessary because "something ^ 0" returns "fromInteger 1", which unfortunately
-- in our case is not our multiplicative identity (the identity matrix) but just a 1x1 matrix of 1
fib n = (last . head . unMat) (Mat [[1, 1], [1, 0]] ^ n)
 
mult :: Num a => [[a]] -> [[a]] -> [[a]]
mult uss vss = map ((\xs -> if null xs then [] else foldl1 (zipWith (+)) xs) . zipWith (flip (map . (*))) vss) uss
Line 704 ⟶ 796:
fromInteger n = Mat [[fromInteger n]]
abs = undefined
signum = undefined</syntaxhighlight>
 
main :: IO ()
main =
do
startTime <- getCPUTime
mapM_ (putStrLn.seeFib) [16,32]
finishTime <- getCPUTime
let diff = ceiling $ fromIntegral (finishTime - startTime) / 1000000000000
let (minute,second) = quotRem diff 60
putStrLn $ "Took: " ++ (show minute) ++ "min" ++ (show second) ++ "s"
</lang>
{{out}}
Timing is on Intel Core i5-4300U CPU, Windows 10 Professional, using GHCi Version 8.6.5:
<pre>
Fibonacci(2^1610) = 73199214460290552832 ... 9727019095530746322755
Fibonacci(2^32100) = 6199931968938185981835422484817926191507 ... 396237355382080763475
Fibonacci(1_000) = 4346655768693745643 ... 76137795166849228875
Took: 4min19s
Fibonacci(10_000) = 3364476487643178326 ... 66073310059947366875
Fibonacci(100_000) = 2597406934722172416 ... 49895374653428746875
Fibonacci(1_000_000) = 1953282128707757731 ... 68996526838242546875
Fibonacci(10_000_000) = 1129834378225399760 ... 86998673686380546875
Fibonacci(2^16) = 7319921446029055283 ... 97270190955307463227
Fibonacci(2^32) = 6199931968938185981 ... 39623735538208076347
Took 3m58.1s
</pre>
 
===Matrix exponentiation for a symmetric matrix===
We will use a property of symmetric matrices which commute.
Line 731 ⟶ 820:
 
At each step of the exponentiation of a symmetric matric, we multiply 2 symmetric matrices which commute.
<langsyntaxhighlight Haskelllang="haskell">-- https://yutsumura.com/symmetric-matrices-and-the-product-of-two-matrices/
import System.CPUTime (getCPUTime)
import Data.List
 
main = do
phi :: Double
startTime <- getCPUTime
phi = (1 + sqrt 5)/2
mapM_ (putStrLn.formatAns).take 7.iterate (*10) $ 10
log10phi = logBase 10 phi
mapM_ (putStrLn.seeFib) [16,32]
halflog10five =(logBase 10 5)/2
finishTime <- getCPUTime
putStrLn $ "Took " ++ (took startTime finishTime)
 
took t = fromChrono.chrono t
 
fromChrono :: (Integer,Integer,Integer) -> String
fromChrono (m,s,ms) = show m ++ "m" ++ show s ++ "." ++ show ms ++ "s"
 
chrono :: Integer -> Integer -> (Integer,Integer,Integer)
chrono start end = (m,s,ms)
where
tera = 1000000000000
fdt = fromIntegral (end - start) / tera
dt = floor fdt
(m,s) = quotRem dt 60
ms = round $ fromIntegral (round (fdt - (fromIntegral dt))*1000) / 1000
 
bagOf :: Int -> [a] -> [[a]]
bagOf _ [] = []
bagOf n xs = let (us,vs) = splitAt n xs in us : bagOf n vs
 
formatIntegral :: Show a => String -> a -> String
formatIntegral sep = reverse.intercalate sep.bagOf 3.reverse.show
 
formatAns :: Integer -> String
formatAns p = start ++ (startEnd 20 (sizeFib p) num)
where
start = "Fibonacci("++ (formatIntegral "_" p) ++ ") = "
num = fib p
 
seeFib :: Integer -> String
seeFib n = start ++ xs(startEnd 20 (sizeFib p) num)
where
start = "Fibonacci(2^" ++ (show n) ++") = "
p = 2^n
xnum = fib p
 
fp = fromIntegral p
startEnd :: (Integral a, Show a) => a -> a -> a -> String
len = floor $ fp*log10phi - halflog10five
startEnd ndigit len num | len <= ndigit = show num
xs = if len <= 40 then show x else (show . quot x $ 10^(len-19)) ++ " ... " ++ (show . rem x $ 10^20)
startEnd ndigit len num | len <= 2*ndigit = let (us,vs) = genericSplitAt ndigit (show num) in us ++ " ... " ++ vs
startEnd ndigit len num = start ++ " ... " ++ end
where
end = show.rem num $ 10 ^ ndigit
start = show.quot num $ 10 ^ (len - ndigit + 1)
 
phi :: Double
phi = (1 + sqrt 5)/2
log10phi = logBase 10 phi
halflog10five =(logBase 10 5)/2
 
sizeFib :: Integral a => a -> a
sizeFib p = ceiling $ (fromIntegral p)*log10phi - halflog10five
 
fib :: Integer -> Integer
fib 0 = 0
fib n = zeroOne (power (Mat 1 1 1 0) n)
 
Line 756 ⟶ 889:
-- for a symmetric matrix
square :: Num a => (Mat a) -> (Mat a)
square (Mat x00 x01 x10 x11) = Mat (x00*x00+x1010)y00 y10 y10 (x11*x11+x1010)y11
where
y00 = y10 + y11 -- F_{n+1} = F_{n} + F_{n-1}
x1010 = x10*x10
y10 = x10*(x00+x11)
y11 = x11*x11+x10*x10
 
-- for 2 symmetric matrices which commute
mult :: Num a => (Mat a) -> (Mat a) -> (Mat a)
mult (Mat x00 x01 x10 x11) (Mat y00 y01 y10 y11) = Mat (x00*y00 + x01*y10)xy00 xy01 xy01 (x10*y01 + x11*y11)xy11
where xy01 = x10*y00 + x11*y10
xy00 = xy01 + xy11 -- F_{n+1} = F_{n} + F_{n-1}
xy01 = x10*y00 + x11*y10
xy11 = x10*y01 + x11*y11
 
power :: Num a => (Mat a) -> Integer -> (Mat a)
power _ n | n < 0 = error "Exception: Negative exponent"
power _ 0 = Mat 1 0 0 1
power m 1 = m
power m n = if even n then w else mult m w m
where w = square.power m.quot n $ 2</syntaxhighlight>
 
main :: IO ()
main =
do
startTime <- getCPUTime
mapM_ (putStrLn.seeFib) [16,32]
finishTime <- getCPUTime
let diff = ceiling $ fromIntegral (finishTime - startTime) / 1000000000000
let (minute,second) = quotRem diff 60
putStrLn $ "Took: " ++ (show minute) ++ "min" ++ (show second) ++ "s"
</lang>
{{out}}
Timing is on Intel Core i5-4300U CPU, Windows 10 Professional, using GHCi Version 8.6.5:
<pre>Fibonacci(10) = 55
Fibonacci(2^16100) = 7319921446029055283235422484817926191507 ... 972701909553074632275
Fibonacci(2^321_000) = 619993196893818598184346655768693745643 ... 3962373553820807634776137795166849228875
Fibonacci(10_000) = 3364476487643178326 ... 66073310059947366875
Took: 2min24s
Fibonacci(100_000) = 2597406934722172416 ... 49895374653428746875
</pre>
Fibonacci(1_000_000) = 1953282128707757731 ... 68996526838242546875
Fibonacci(10_000_000) = 1129834378225399760 ... 86998673686380546875
Fibonacci(2^16) = 7319921446029055283 ... 97270190955307463227
Fibonacci(2^32) = 6199931968938185981 ... 39623735538208076347
Took 2m6.1s</pre>
 
=={{header|Java}}==
Line 795 ⟶ 927:
Implemented fib and fibMod.
 
<langsyntaxhighlight lang="java">
import java.math.BigInteger;
import java.util.Arrays;
Line 878 ⟶ 1,010:
 
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 892 ⟶ 1,024:
fib(1,000,000) = 19532821287077577316 ... 68996526838242546875
fib(10,000,000) = 11298343782253997603 ... 86998673686380546875
</pre>
 
=={{header|jq}}==
'''Adapted from [[#Wren]]'''
<br>
'''Works with gojq, the Go implementation of jq''' (*)
 
(*) The C implementation of jq only has support for IEEE 754 64-bit numbers.
 
In the first part of this entry, the matrix method is used; the second part uses a recurrence relation for Fib(2^n) that is significantly faster, but still not practical for computing Fib(2^32).
====Matrix Exponentiation====
<syntaxhighlight lang="jq">def mul($m1; $m2):
($m1|length) as $rows1
| ($m1[0]|length) as $cols1
| ($m2|length) as $rows2
| ($m2[0]|length) as $cols2
| if ($cols1 != $rows2) then "Matrices cannot be multiplied."| error
else reduce range(0; $rows1) as $i (null;
reduce range(0; $cols2) as $j (.;
.[$i][$j] = 0
| reduce range(0; $rows2) as $k (.;
.[$i][$j] += $m1[$i][$k] * $m2[$k][$j])
) )
end ;
def identityMatrix:
. as $n
| [range(0; .) | 0] as $row
| [range(0; .) | $row]
| reduce range(0;$n) as $i (.;
.[$i][$i] = 1 );
 
# . should be a square matrix and $n >= 0
def pow( $n ):
. as $m
| ($m|length) as $le
| if $n < 0 then "Negative exponents not supported" | error
elif $n == 0 then $le|identityMatrix
elif $n == 1 then $m
else {pow : ($le | identityMatrix),
base : $m,
e : $n }
| until( .e <= 0.5;
# debug|
 
(.e % 2) as $temp
| if $temp == 1 then .pow = mul(.pow; .base) else . end
| .e /= 2
| .base = mul(.base; .base) )
| .pow
end;
 
def fibonacci:
. as $n
| if $n == 0 then 0
else {m: [[1, 1], [1, 0]]}
| .m |= pow($n - 1)
| .m[0][0]
end;
 
def task1:
{ i: 10 }
| while ( .i <= 1e7;
.n = .i
| .s = (.n|fibonacci|tostring)
| .i *= 10)
| select(.s)
| "\nThe digits of the \(.n)th Fibonacci number (\(.s|length)) are:",
(if .s|length > 20
then " First 20 : \(.s[0:20])",
( if (.s|length < 40)
then "\n Final \(.s|length-20): \(.s[20:])"
else " Final 20 : \(.s[-20:])"
end )
else " All \(.s|length) : \(.s)"
end) ;
 
def task2:
pow(2;16) as $n
| (($n|fibonacci)|tostring) as $s
| "The digits of the 2^16th Fibonacci number \($s|length) are:",
" First 20 : \($s[0:20])",
" Final 20 : \($s[-20:])";
 
task1, "", task2</syntaxhighlight>
{{out}}
<pre>
The digits of the 10th Fibonacci number (2) are:
All 2 : 55
 
The digits of the 100th Fibonacci number (21) are:
First 20 : 35422484817926191507
Final 1: 5
 
The digits of the 1000th Fibonacci number (209) are:
First 20 : 43466557686937456435
Final 20 : 76137795166849228875
 
The digits of the 10000th Fibonacci number (2090) are:
First 20 : 33644764876431783266
Final 20 : 66073310059947366875
 
The digits of the 100000th Fibonacci number (20899) are:
First 20 : 25974069347221724166
Final 20 : 49895374653428746875
 
The digits of the 1000000th Fibonacci number (208988) are:
First 20 : 19532821287077577316
Final 20 : 68996526838242546875
 
The digits of the 2^16th Fibonacci number 13696 are:
First 20 : 73199214460290552832
Final 20 : 97270190955307463227
</pre>
 
====Fib(2^n)====
<syntaxhighlight lang="jq"># Input: n
# Output: Fib(2^n)
def Fib2pN:
# in: [p, Fn-1, Fn] where n==2^p
# out: [2p, F(2n-1),F(2n)]
def fibonacci_recurrence:
def sq: .*.;
. as [$p, $fprev, $f]
| [1+$p, ($f|sq) + ($fprev|sq), (2*$fprev + $f)*$f];
. as $n
| [0,0,1]
| until( .[0] >= $n; fibonacci_recurrence)
| .[2] ;
 
 
16, 32
| . as $i
| Fib2pN
| tostring
| "The digits of the 2^\($i)th Fibonacci number (with string length \(length)) are:",
" First 20 : \(.[0:20])",
" Final 20 : \(.[-20:])",
""</syntaxhighlight>
{{out}}
Using gojq to compute Fib(2^32) using this method takes many hours.
<pre>
The digits of the 2^16th Fibonacci number (with string length 13696) are:
First 20 : 73199214460290552832
Final 20 : 97270190955307463227
 
The digits of the 2^32 Fibonacci number (with string length 897595080) are:
First 20 : 61999319689381859818
Final 20 : 39623735538208076347
</pre>
 
Line 898 ⟶ 1,179:
the 2^64-th fibonacchi number, due to BigInt overflow. The Binet method actually overflows even with the 2^32-nd fibonacchi number, so the
Lucas method is used as the alternative method.
<langsyntaxhighlight lang="julia"># Here is the matrix Fibonacci formula as specified to be used for the solution.
const b = [big"1" 1; 1 0]
matrixfibonacci(n) = n == 0 ? 0 : n == 1 ? 1 : (b^(n+1))[2,2]
Line 961 ⟶ 1,242:
rpad(firstlast(firstbinet(32) * lastfibmod(32)), 45))
println("2^64 ", " "^90, rpad(firstlast(firstbinet(64) * lastfibmod(64)), 45))
</langsyntaxhighlight>{{out}}
<pre>
N Matrix Lucas Mod
Line 969 ⟶ 1,250:
2^64 11175807536929528424...17529800348089840187
</pre>
 
=={{header|Nim}}==
{{trans|Wren}}
{{trans|Go}}
Using the Lucas method.
<syntaxhighlight lang="nim">import strformat, strutils, times
import bignum
 
let
One = newInt(1)
Two = newInt(2)
Three = newInt(3)
 
proc lucas(n: Int): Int =
 
proc inner(n: Int): (Int, Int) =
if n.isZero: return (newInt(0), newInt(1))
var t = n shr 1
var (u, v) = inner(t)
t = n and Two
let q = t - One
var r = newInt(0)
u *= u
v *= v
t = n and One
if t == One:
t = (u - q) * Two
r = v * Three
result = (u + v, r - t)
else:
t = u * Three
r = v + q
r *= Two
result = (r - t, u + v)
 
var t = n shr 1
let (u, v) = inner(t)
let l = v * Two - u
t = n and One
if t == One:
let q = n and Two - One
return v * l + q
 
return u * l
 
let start = now()
 
var n: Int
var i = 10
while i <= 10_000_000:
n = newInt(i)
let s = $lucas(n)
 
echo &"The digits of the {($i).insertSep}th Fibonacci number ({($s.len).insertSep}) are:"
if s.len > 20:
echo &" First 20 : {s[0..19]}"
if s.len < 40:
echo &" Final {s.len-20:<2} : {s[20..^1]}"
else:
echo &" Final 20 : {s[^20..^1]}"
else:
echo &" All {s.len:<2} : {s}"
echo()
i *= 10
 
for e in [culong 16, 32]:
n = One shl e
let s = $lucas(n)
echo &"The digits of the 2^{e}th Fibonacci number ({($s.len).insertSep}) are:"
echo &" First 20 : {s[0..19]}"
echo &" Final 20 : {s[^20..^1]}"
echo()
 
echo &"Took {now() - start}"</syntaxhighlight>
 
{{out}}
<pre>The digits of the 10th Fibonacci number (2) are:
All 2 : 55
 
The digits of the 100th Fibonacci number (21) are:
First 20 : 35422484817926191507
Final 1 : 5
 
The digits of the 1_000th Fibonacci number (209) are:
First 20 : 43466557686937456435
Final 20 : 76137795166849228875
 
The digits of the 10_000th Fibonacci number (2_090) are:
First 20 : 33644764876431783266
Final 20 : 66073310059947366875
 
The digits of the 100_000th Fibonacci number (20_899) are:
First 20 : 25974069347221724166
Final 20 : 49895374653428746875
 
The digits of the 1_000_000th Fibonacci number (208_988) are:
First 20 : 19532821287077577316
Final 20 : 68996526838242546875
 
The digits of the 10_000_000th Fibonacci number (2_089_877) are:
First 20 : 11298343782253997603
Final 20 : 86998673686380546875
 
The digits of the 2^16th Fibonacci number (13_696) are:
First 20 : 73199214460290552832
Final 20 : 97270190955307463227
 
The digits of the 2^32th Fibonacci number (897_595_080) are:
First 20 : 61999319689381859818
Final 20 : 39623735538208076347
 
Took 6 minutes, 18 seconds, 643 milliseconds, 622 microseconds, and 965 nanoseconds</pre>
 
=={{header|Perl}}==
{{trans|Sidef}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
 
Line 1,011 ⟶ 1,404:
my $last20 = nth_fib_last_k_digits(2**$n, 20);
printf "F(2^$n) = %s ... %s\n", $first20, $last20;
}</langsyntaxhighlight>
{{out}}
<pre>F(2^16) = 73199214460290552832 ... 97270190955307463227
Line 1,020 ⟶ 1,413:
F(2^64) = 11175807536929528424 ... 17529800348089840187</pre>
 
=={{header|Perl 6Phix}}==
{{libheader|Phix/mpfr}} {{trans|Sidef}} Since I don't have a builtin fibmod, I had to roll my own, and used {n,m} instead of(/to mean) 2^n+m, thus avoiding some 2^53 native atom limits on 32-bit.<br>
(mpz and mpfr variables are effectively pointers, and therefore simply won't work as expected/needed should you try and use them as keys to a cache.)
<!--<syntaxhighlight lang="phix">-->
<span style="color: #008080;">without</span> <span style="color: #008080;">javascript_semantics</span> <span style="color: #000080;font-style:italic;">-- (no mpfr_log(), mpfr_exp() under pwa/p2js)</span>
<span style="color: #7060A8;">requires</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1.0.0"</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (mpfr_set_default_prec[ision] has been renamed)</span>
<span style="color: #008080;">include</span> <span style="color: #004080;">mpfr</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #7060A8;">mpfr_set_default_precision</span><span style="color: #0000FF;">(-</span><span style="color: #000000;">40</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">PHI</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpfr_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1.25</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">IHP</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpfr_init</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">HLF</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpfr_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">L10</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpfr_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpfr_sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">PHI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PHI</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpfr_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">IHP</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PHI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">HLF</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpfr_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">PHI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PHI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">HLF</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mpfr_neg</span><span style="color: #0000FF;">(</span><span style="color: #000000;">IHP</span><span style="color: #0000FF;">,</span><span style="color: #000000;">IHP</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mpfr_log</span><span style="color: #0000FF;">(</span><span style="color: #000000;">L10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">L10</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">binet_approx</span><span style="color: #0000FF;">(</span><span style="color: #004080;">mpfr</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">mpfr</span> <span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpfr_init</span><span style="color: #0000FF;">()</span>
<span style="color: #000000;">mpfr_ui_pow_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- (n as in 2^n here)</span>
<span style="color: #000000;">mpfr_log</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PHI</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpfr_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpfr_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">PHI</span><span style="color: #0000FF;">,</span><span style="color: #000000;">IHP</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mpfr_log</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpfr_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpfr_free</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">nth_fib_first_k_digits</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">mpfr</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">h</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpfr_inits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">binet_approx</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpfr_div</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">L10</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mpfr_add_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mpfr_floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">g</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpfr_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">L10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">g</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpfr_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">g</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mpfr_exp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mpfr_ui_pow_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">h</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpfr_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">h</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mpfr_floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">fmt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%%%d.0Rf"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">mpfr_sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">cache</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">()</span>
<span style="color: #000080;font-style:italic;">-- key of {n,m} means 2^n+m (where n and m are integers, n&gt;=0, m always 0 or -1)</span>
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">({</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span><span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">),</span><span style="color: #000000;">cache</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- aka fib(0):=0</span>
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">({</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span><span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span><span style="color: #000000;">cache</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- fib(1):=1</span>
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">({</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},</span><span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span><span style="color: #000000;">cache</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- fib(2):=1</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">mpz_fibmod</span><span style="color: #0000FF;">(</span><span style="color: #004080;">mpz</span> <span style="color: #000000;">f</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">key</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">getd_index</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cache</span><span style="color: #0000FF;">)!=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">mpz_set</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">getd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cache</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">else</span>
<span style="color: #004080;">mpz</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">f1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f2</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_inits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">n</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">1</span>
<span style="color: #000000;">mpz_fibmod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mpz_fibmod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">-- fib(2n-1) = fib(n)^2 + fib(n-1)^2</span>
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f1</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f2</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #000080;font-style:italic;">-- fib(2n) = (2*fib(n-1)+fib(n))*fib(n)</span>
<span style="color: #7060A8;">mpz_mul_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f1</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">mpz_mod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">key</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cache</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_set</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">nth_fib_last_k_digits</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">mpz</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_inits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_ui_pow_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">mpz_fibmod</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">16</span><span style="color: #0000FF;">,</span><span style="color: #000000;">32</span><span style="color: #0000FF;">,</span><span style="color: #000000;">64</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">first20</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nth_fib_first_k_digits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">20</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">last20</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">nth_fib_last_k_digits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">20</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"F(2^%d) = %s ... %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">first20</span><span style="color: #0000FF;">,</span><span style="color: #000000;">last20</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
F(2^16) = 73199214460290552832 ... 97270190955307463227
F(2^32) = 61999319689381859818 ... 39623735538208076347
F(2^64) = 11175807536929528424 ... 17529800348089840187
</pre>
===matrix exponentiation (2^16)===
Somewhat closer to the original specification, but certainly not recommended for 2^32, let alone 2^64...<br>
Contains copies of routines from [[Matrix-exponentiation_operator#Phix]], but modified to use gmp.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">include</span> <span style="color: #004080;">mpfr</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">ZERO</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">ONE</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">identity</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ZERO</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">),</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ONE</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">matrix_mul</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])!=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"matrices cannot be multiplied"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ZERO</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])),</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">mpz</span> <span style="color: #000000;">cij</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cij</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">k</span><span style="color: #0000FF;">],</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</span>
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cij</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cij</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</span>
<span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">cij</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">c</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">matrix_exponent</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">!=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"not a square matrix"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"negative exponents not supported"</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">identity</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">matrix_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">floor</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> <span style="color: #000080;font-style:italic;">-- (avoid unnecessary matrix_mul)</span>
<span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">matrix_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">fibonacci</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">ONE</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ONE</span><span style="color: #0000FF;">},</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">ONE</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ZERO</span><span style="color: #0000FF;">}}</span>
<span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">matrix_exponent</span><span style="color: #0000FF;">(</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">mpz</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">][</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">mpz</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fibonacci</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">16</span><span style="color: #0000FF;">))</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"fibonnaci(2^16) = %s [%s]\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">shorten</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">),</span><span style="color: #000000;">e</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">JS</span><span style="color: #0000FF;">?</span><span style="color: #000000;">6</span><span style="color: #0000FF;">:</span><span style="color: #000000;">7</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">fibonacci</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_get_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span>
<span style="color: #000000;">e</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">></span><span style="color: #000000;">0.1</span><span style="color: #0000FF;">?</span><span style="color: #008000;">" ["</span><span style="color: #0000FF;">&</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)&</span><span style="color: #008000;">"]"</span><span style="color: #0000FF;">:</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"fibonnaci(%,d) = %s%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">shorten</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">),</span><span style="color: #000000;">e</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
fibonnaci(2^16) = 73199214460290552832...97270190955307463227 (13,696 digits) [0s]
fibonnaci(10) = 55
fibonnaci(100) = 354224848179261915075
fibonnaci(1,000) = 43466557686937456435...76137795166849228875 (209 digits)
fibonnaci(10,000) = 33644764876431783266...66073310059947366875 (2,090 digits)
fibonnaci(100,000) = 25974069347221724166...49895374653428746875 (20,899 digits)
fibonnaci(1,000,000) = 19532821287077577316...68996526838242546875 (208,988 digits) [0.2s]
fibonnaci(10,000,000) = 11298343782253997603...86998673686380546875 (2,089,877 digits) [9.0s]
</pre>
Note that under pwa/p2js 10^6 takes 11.4s so we'll stop there...<br>
Change that loop to 8 and a 9 year old 3.3GHz i3 also eventually gets:
<pre>
fibonnaci(100,000,000) = 47371034734563369625...06082642167760546875 (20,898,764 digits) [14 minutes and 24s]
</pre>
Clearly 2^32 (897 million digits, apparently) is a tad out of bounds, let alone 2^64.
 
=={{header|Python}}==
With fancy custom integer classes that are absolutely useless except for this task.
<syntaxhighlight lang="python">class Head():
def __init__(self, lo, hi=None, shift=0):
if hi is None: hi = lo
 
d = hi - lo
ds, ls, hs = str(d), str(lo), str(hi)
 
if d and len(ls) > len(ds):
assert(len(ls) - len(ds) + 1 > 21)
lo = int(str(lo)[:len(ls) - len(ds) + 1])
hi = int(str(hi)[:len(hs) - len(ds) + 1]) + 1
shift += len(ds) - 1
elif len(ls) > 100:
lo = int(str(ls)[:100])
hi = lo + 1
shift = len(ls) - 100
 
self.lo, self.hi, self.shift = lo, hi, shift
 
def __mul__(self, other):
lo = self.lo*other.lo
hi = self.hi*other.hi
shift = self.shift + other.shift
 
return Head(lo, hi, shift)
 
def __add__(self, other):
if self.shift < other.shift:
return other + self
 
sh = self.shift - other.shift
if sh >= len(str(other.hi)):
return Head(self.lo, self.hi, self.shift)
 
ls = str(other.lo)
hs = str(other.hi)
 
lo = self.lo + int(ls[:len(ls)-sh])
hi = self.hi + int(hs[:len(hs)-sh])
 
return Head(lo, hi, self.shift)
 
def __repr__(self):
return str(self.hi)[:20]
 
class Tail():
def __init__(self, v):
self.v = int(f'{v:020d}'[-20:])
 
def __add__(self, other):
return Tail(self.v + other.v)
 
def __mul__(self, other):
return Tail(self.v*other.v)
 
def __repr__(self):
return f'{self.v:020d}'[-20:]
def mul(a, b):
return a[0]*b[0] + a[1]*b[1], a[0]*b[1] + a[1]*b[2], a[1]*b[1] + a[2]*b[2]
 
def fibo(n, cls):
n -= 1
zero, one = cls(0), cls(1)
m = (one, one, zero)
e = (one, zero, one)
 
while n:
if n&1: e = mul(m, e)
m = mul(m, m)
n >>= 1
 
return f'{e[0]}'
 
for i in range(2, 10):
n = 10**i
print(f'10^{i} :', fibo(n, Head), '...', fibo(n, Tail))
 
for i in range(3, 8):
n = 2**i
s = f'2^{n}'
print(f'{s:5s}:', fibo(2**n, Head), '...', fibo(2**n, Tail))</syntaxhighlight>
{{out}}
<pre>10^2 : 35422484817926191507 ... 54224848179261915075
10^3 : 43466557686937456435 ... 76137795166849228875
10^4 : 33644764876431783266 ... 66073310059947366875
10^5 : 25974069347221724166 ... 49895374653428746875
10^6 : 19532821287077577316 ... 68996526838242546875
10^7 : 11298343782253997603 ... 86998673686380546875
10^8 : 47371034734563369625 ... 06082642167760546875
10^9 : 79523178745546834678 ... 03172326981560546875
2^8 : 14169381771405651323 ... 19657707794958199867
2^16 : 73199214460290552832 ... 97270190955307463227
2^32 : 61999319689381859818 ... 39623735538208076347
2^64 : 11175807536929528424 ... 17529800348089840187
2^128: 15262728879740471565 ... 17229324095882654267</pre>
=={{header|Ruby}}==
===Matrix exponentiation by Ruby's fast exponentiation operator duck-typing applied to Ruby's built-in Integer Class===
<pre>
require 'matrix'
start_time = Time.now
[0,1,2,3,4,10,100,256, 1_000, 1024, 10_000, 2 ** 16, 100_000, 1_000_000,10_000_000 ].each {|n|
##
fib_Num=(Matrix[[0,1],[1,1]] ** (n))[0,1] ## Matrix exponentiation
##
fib_Str= fib_Num.to_s()
if fib_Str.length <= 21
p ["Fibonacci(#{n})",fib_Str.length.to_s + ' digits' , fib_Str]
else
p ["Fibonacci(#{n})",fib_Str.length.to_s + ' digits' , fib_Str.slice(0,20) + " ... " + fib_Str.slice(-20,20)]
end
}
puts "Took #{Time.now - start_time}s"
 
</pre>
 
{{out}}
<pre>
["Fibonacci(0)", "1 digits", "0"]
["Fibonacci(1)", "1 digits", "1"]
["Fibonacci(2)", "1 digits", "1"]
["Fibonacci(3)", "1 digits", "2"]
["Fibonacci(4)", "1 digits", "3"]
["Fibonacci(10)", "2 digits", "55"]
["Fibonacci(100)", "21 digits", "354224848179261915075"]
["Fibonacci(256)", "54 digits", "14169381771405651323 ... 19657707794958199867"]
["Fibonacci(1000)", "209 digits", "43466557686937456435 ... 76137795166849228875"]
["Fibonacci(1024)", "214 digits", "45066996336778198131 ... 04103631553925405243"]
["Fibonacci(10000)", "2090 digits", "33644764876431783266 ... 66073310059947366875"]
["Fibonacci(65536)", "13696 digits", "73199214460290552832 ... 97270190955307463227"]
["Fibonacci(100000)", "20899 digits", "25974069347221724166 ... 49895374653428746875"]
["Fibonacci(1000000)", "208988 digits", "19532821287077577316 ... 68996526838242546875"]
["Fibonacci(10000000)", "2089877 digits", "11298343782253997603 ... 86998673686380546875"]
Took 1.027948065s
</pre>
 
===Matrix exponentiation by Ruby's Matlix#exponentiation duck-typeing with Head-tail-BigNumber class===
Here, the HeadTailBignum class holds the digits of the head part in Ruby's bigDecimal class and tail part in the BigInteger class.
and HeadTailBignum defines only the add and multply operators and the coerce method.
 
Matlix exponentiation operator is fast and can apply duck-typing to HeadTailBignum.
 
require 'matrix'
require 'bigdecimal'
class HeadTailBignum < Numeric
attr_accessor :hi, :lo
@@degitsLimit = 20
@@hiDegitsLimit = (@@degitsLimit + 1) * 2
@@loDegitsBase = 10 ** @@degitsLimit
BigDecimal::limit(@@hiDegitsLimit)
def initialize(other, loValue = nil)
if other.kind_of?(BigDecimal) && loValue.kind_of?(Integer)
@hi = other
@lo = loValue % @@loDegitsBase
elsif other.kind_of?(HeadTailBignum)
@hi = other.hi
@lo = other.lo
elsif other.kind_of?(Integer)
@hi = BigDecimal(other)
@lo = other % @@loDegitsBase
else
raise StandardError.new("HeadTailBignum initialize Type Error (" + other.class.to_s + "," + loValue.class.to_s + ")")
end
end
def clone
HeadTailBignum(self.hi, self.lo)
end
def integer?()
true
end
def coerce(other)
if other.kind_of?(Integer)
return HeadTailBignum.new(other), self
else
super
end
end
def +(other)
if other.kind_of?(Integer)
return HeadTailBignum.new(self.hi + other, self.lo + other)
elsif other.kind_of?(HeadTailBignum)
return HeadTailBignum.new(self.hi + other.hi , self.lo + other.lo)
else
raise StandardError.new("HeadTailBignum add Type Error (" + other.class.to_s + ")")
end
end
def *(other)
if other.kind_of?(Integer)
return HeadTailBignum.new(self.hi * other, self.lo * other)
elsif other.kind_of?(HeadTailBignum)
return HeadTailBignum.new(self.hi * other.hi , self.lo * other.lo)
else
raise StandardError.new("HeadTailBignum mulply Type Error (" + other.class.to_s + ")")
end
end
def exponent
@hi.exponent
end
def to_s
if @hi < @@loDegitsBase
return @lo.inspect
else
return @hi.to_s("E").slice(2,@@degitsLimit ) + " ... " + @lo.to_s
end
end
end
start_time = Time.now
[8,16,32,64].each {|h|
n = (2**h)
fib_Num=(Matrix[[ HeadTailBignum.new(0),1],[1,1]] ** (n))[0,1]
puts "Fibonacci(2^#{h.to_s}) = #{fib_Num.to_s} are #{fib_Num.exponent} digits"
}
puts "Took #{Time.now - start_time}s"
 
{{out}}
<pre>
Fibonacci(2^8) = 14169381771405651323 ... 19657707794958199867 are 54 digits
Fibonacci(2^16) = 73199214460290552832 ... 97270190955307463227 are 13696 digits
Fibonacci(2^32) = 61999319689381859818 ... 39623735538208076347 are 897595080 digits
Fibonacci(2^64) = 11175807536929528424 ... 17529800348089840187 are 3855141514259838964 digits
Took 0.009357194s
</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
Following the general approach of Sidef, and relying on Perl for <code>fibmod</code> function. Borrowed/adapted routines from [http://rosettacode.org/wiki/Ramanujan%27s_constant Ramanujan's_constant] task to allow <code>FatRat</code> calculations throughout. Does not quite meet task spec, as n^64 results not working yet.
<syntaxhighlight lang="raku" perl6line>use Math::Matrix;
use Inline::Perl5;
my $p5 = Inline::Perl5.new();
Line 1,127 ⟶ 1,945:
my $last20 = nth_fib_last_k_digits(2**$n, 20);
printf "F(2^$n) = %s ... %s\n", $first20, $last20
}</langsyntaxhighlight>
{{out}}
<pre>F(2^16) = 73199214460290552832 ... 97270190955307463227
Line 1,133 ⟶ 1,951:
F(2^16) = 73199214460290552832 ... 97270190955307463227
F(2^32) = 61999319689381859818 ... 39623735538208076347</pre>
 
=={{header|Phix}}==
{{libheader|mpfr}} {{trans|Sidef}} Since I don't have a builtin fibmod, I had to roll my own, and used {n,m} instead of(/to mean) 2^n+m, thus avoiding some 2^53 native atom limits on 32-bit.<br>
(mpz and mpfr variables are effectively pointers, and therefore simply won't work as expected/needed should you try and use them as keys to a cache.)
<lang Phix>include mpfr.e
mpfr_set_default_prec(-40)
 
constant PHI = mpfr_init(1.25),
IHP = mpfr_init(),
HLF = mpfr_init(0.5),
L10 = mpfr_init(10)
mpfr_sqrt(PHI,PHI)
mpfr_sub(IHP,PHI,HLF)
mpfr_add(PHI,PHI,HLF)
mpfr_neg(IHP,IHP)
mpfr_log(L10,L10)
 
procedure binet_approx(mpfr r, integer n)
mpfr m = mpfr_init()
mpfr_ui_pow_ui(m,2,n) -- (n as in 2^n here)
mpfr_log(r,PHI)
mpfr_mul(r,r,m)
mpfr_sub(m,PHI,IHP)
mpfr_log(m,m)
mpfr_sub(r,r,m)
m = mpfr_free(m)
end procedure
function nth_fib_first_k_digits(integer n, k)
mpfr {f,g,h} = mpfr_inits(3)
binet_approx(f,n)
mpfr_div(g,f,L10)
mpfr_add_si(g,g,1)
mpfr_floor(g,g)
mpfr_mul(g,L10,g)
mpfr_sub(f,f,g)
mpfr_exp(f,f)
mpfr_ui_pow_ui(h,10,k)
mpfr_mul(f,f,h)
mpfr_floor(f,f)
string fmt = sprintf("%%%d.0Rf",k)
return mpfr_sprintf(fmt,f)
end function
integer cache = new_dict()
-- key of {n,m} means 2^n+m (where n and m are integers, n>=0, m always 0 or -1)
setd({0,0},mpz_init(0),cache) -- aka fib(0):=0
setd({1,-1},mpz_init(1),cache) -- fib(1):=1
setd({1,0},mpz_init(1),cache) -- fib(2):=1
 
procedure mpz_fibmod(mpz f, p, integer n, m=0)
sequence key = {n,m}
if getd_index(key,cache)!=NULL then
mpz_set(f,getd(key,cache))
else
mpz {f1,f2} = mpz_inits(2)
n -= 1
mpz_fibmod(f1,p,n)
mpz_fibmod(f2,p,n,-1)
if m=-1 then
-- fib(2n-1) = fib(n)^2 + fib(n-1)^2
mpz_mul(f1,f1,f1)
mpz_mul(f2,f2,f2)
mpz_add(f1,f1,f2)
else
-- fib(2n) = (2*fib(n-1)+fib(n))*fib(n)
mpz_mul_si(f2,f2,2)
mpz_add(f2,f2,f1)
mpz_mul(f1,f2,f1)
end if
mpz_mod(f1,f1,p)
setd(key,f1,cache)
mpz_set(f,f1)
end if
end procedure
function nth_fib_last_k_digits(integer n, k)
mpz {f,p} = mpz_inits(2)
mpz_ui_pow_ui(p,10,k)
mpz_fibmod(f,p,n)
return mpz_get_str(f)
end function
constant tests = {16,32,64}
for i=1 to length(tests) do
integer n = tests[i]
string first20 = nth_fib_first_k_digits(n, 20),
last20 = nth_fib_last_k_digits(n, 20)
printf(1,"F(2^%d) = %s ... %s\n",{n,first20,last20})
end for</lang>
{{out}}
<pre>
F(2^16) = 73199214460290552832 ... 97270190955307463227
F(2^32) = 61999319689381859818 ... 39623735538208076347
F(2^64) = 11175807536929528424 ... 17529800348089840187
</pre>
===matrix exponentiation (2^16)===
Somewhat closer to the original specification, but certainly not recommended for 2^32, let alone 2^64...<br>
Contains copies of routines from [[Matrix-exponentiation_operator#Phix]], but modified to use gmp.
<lang Phix>include mpfr.e
 
constant ZERO = mpz_init(0),
ONE = mpz_init(1)
 
function identity(integer n)
sequence res = repeat(repeat(ZERO,n),n)
for i=1 to n do
res[i][i] = ONE
end for
return res
end function
function matrix_mul(sequence a, sequence b)
if length(a[1])!=length(b) then
crash("matrices cannot be multiplied")
end if
sequence c = repeat(repeat(ZERO,length(b[1])),length(a))
for i=1 to length(a) do
for j=1 to length(b[1]) do
for k=1 to length(a[1]) do
mpz cij = mpz_init()
mpz_mul(cij,a[i][k],b[k][j])
mpz_add(cij,cij,c[i][j])
c[i][j] = cij
end for
end for
end for
return c
end function
function matrix_exponent(sequence m, integer n)
integer l = length(m)
if l!=length(m[1]) then crash("not a square matrix") end if
if n<0 then crash("negative exponents not supported") end if
sequence res = identity(l)
while n do
if and_bits(n,1) then
res = matrix_mul(res,m)
end if
n = floor(n/2)
if n=0 then exit end if -- (avoid unnecessary matrix_mul)
m = matrix_mul(m,m)
end while
return res
end function
function fibonacci(integer n)
sequence m = {{ONE, ONE},
{ONE, ZERO}}
m = matrix_exponent(m,n-1)
mpz res = m[1][1]
return res
end function
 
atom t0 = time()
mpz fn = fibonacci(power(2,16))
string s = mpz_get_str(fn)
string e = elapsed(time()-t0)
printf(1,"fibonnaci(2^16) = %s [%s]\n",{shorten(s),e})
 
for i=1 to 7 do
t0 = time()
integer n = power(10,i)
fn = fibonacci(n)
s = mpz_get_str(fn)
t0 = time()-t0
e = iff(t0>0.1?" ["&elapsed(t0)&"]":"")
printf(1,"fibonnaci(%,d) = %s%s\n",{n,shorten(s),e})
end for</lang>
{{out}}
<pre>
fibonnaci(2^16) = 73199214460290552832...97270190955307463227 (13,696 digits) [0s]
fibonnaci(10) = 55
fibonnaci(100) = 354224848179261915075
fibonnaci(1,000) = 43466557686937456435...76137795166849228875 (209 digits)
fibonnaci(10,000) = 33644764876431783266...66073310059947366875 (2,090 digits)
fibonnaci(100,000) = 25974069347221724166...49895374653428746875 (20,899 digits)
fibonnaci(1,000,000) = 19532821287077577316...68996526838242546875 (208,988 digits) [0.2s]
fibonnaci(10,000,000) = 11298343782253997603...86998673686380546875 (2,089,877 digits) [9.0s]
</pre>
Change that loop to 8 and a 9 year old 3.3GHz i3 also eventually gets:
<pre>
fibonnaci(100,000,000) = 47371034734563369625...06082642167760546875 (20,898,764 digits) [14 minutes and 24s]
</pre>
Clearly 2^32 (897 million digits, apparently) is a tad out of bounds, let alone 2^64.
 
=={{header|Sidef}}==
Computing the n-th Fibonacci number, using matrix-exponentiation (this function is also built-in):
<langsyntaxhighlight lang="ruby">func fibonacci(n) {
([[1,1],[1,0]]**n)[0][1]
}
 
say 15.of(fibonacci) #=> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]</langsyntaxhighlight>
 
First and last 20 digits of the n-th Fibonacci number:
<langsyntaxhighlight lang="ruby">for n in (16, 32) {
 
var f = fibonacci(2**n)
Line 1,337 ⟶ 1,970:
say "F(2^#{n}) = #{a} ... #{b}"
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,345 ⟶ 1,978:
 
More efficient approach, using Binet's formula for computing the first k digits, combined with the built-in method '''fibmod(n,m)''' for computing the last k digits:
<langsyntaxhighlight lang="ruby">func binet_approx(n) {
const PHI = (1.25.sqrt + 0.5)
const IHP = -(1.25.sqrt - 0.5)
Line 1,364 ⟶ 1,997:
var last20 = nth_fib_last_k_digits(2**n, 20)
say "F(2^#{n}) = #{first20} ... #{last20}"
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,370 ⟶ 2,003:
F(2^32) = 61999319689381859818 ... 39623735538208076347
F(2^64) = 11175807536929528424 ... 17529800348089840187
</pre>
 
=={{header|Wren}}==
===Matrix exponentiation===
{{trans|Go}}
{{libheader|Wren-big}}
{{libheader|Wren-fmt}}
A tough task for Wren which takes just under 3 minutes to process even the 1 millionth Fibonacci number. Judging by the times for the compiled, statically typed languages using GMP, the 10 millionth would likely take north of 4 hours so I haven't attempted it.
<syntaxhighlight lang="wren">import "./big" for BigInt
import "./fmt" for Fmt
 
var mul = Fn.new { |m1, m2|
var rows1 = m1.count
var cols1 = m1[0].count
var rows2 = m2.count
var cols2 = m2[0].count
if (cols1 != rows2) Fiber.abort("Matrices cannot be multiplied.")
var result = List.filled(rows1, null)
for (i in 0...rows1) {
result[i] = List.filled(cols2, null)
for (j in 0...cols2) {
result[i][j] = BigInt.zero
for (k in 0...rows2) {
var temp = m1[i][k] * m2[k][j]
result[i][j] = result[i][j] + temp
}
}
}
return result
}
 
var identityMatrix = Fn.new { |n|
if (n < 1) Fiber.abort("Size of identity matrix can't be less than 1")
var ident = List.filled(n, 0)
for (i in 0...n) {
ident[i] = List.filled(n, null)
for(j in 0...n) ident[i][j] = (i != j) ? BigInt.zero : BigInt.one
}
return ident
}
 
var pow = Fn.new { |m, n|
var le = m.count
if (le != m[0].count) Fiber.abort("Not a square matrix")
if (n < 0) Fiber.abort("Negative exponents not supported")
if (n == 0) return identityMatrix.call(le)
if (n == 1) return m
var pow = identityMatrix.call(le)
var base = m
var e = n
while (e > 0) {
var temp = e & BigInt.one
if (temp == BigInt.one) pow = mul.call(pow, base)
e = e >> 1
base = mul.call(base, base)
}
return pow
}
 
var fibonacci = Fn.new { |n|
if (n == 0) return BigInt.zero
var m = [[BigInt.one, BigInt.one], [BigInt.one, BigInt.zero]]
m = pow.call(m, n - 1)
return m[0][0]
}
 
var n = BigInt.zero
var i = 10
while (i <= 1e6) {
n = BigInt.new(i)
var s = fibonacci.call(n).toString
Fmt.print("The digits of the $,sth Fibonacci number ($,s) are:", i, s.count)
if (s.count > 20) {
Fmt.print(" First 20 : $s", s[0...20])
if (s.count < 40) {
Fmt.print(" Final $-2d : $s", s.count-20, s[20..-1])
} else {
Fmt.print(" Final 20 : $s", s[s.count-20..-1])
}
} else {
Fmt.print(" All $-2d : $s", s.count, s)
}
System.print()
i = i * 10
}
n = BigInt.one << 16
var s = fibonacci.call(n).toString
Fmt.print("The digits of the 2^16th Fibonacci number ($,s) are:", s.count)
Fmt.print(" First 20 : $s", s[0...20])
Fmt.print(" Final 20 : $s", s[s.count-20..-1])</syntaxhighlight>
 
{{out}}
<pre>
The digits of the 10th Fibonacci number (2) are:
All 2 : 55
 
The digits of the 100th Fibonacci number (21) are:
First 20 : 35422484817926191507
Final 1 : 5
 
The digits of the 1,000th Fibonacci number (209) are:
First 20 : 43466557686937456435
Final 20 : 76137795166849228875
 
The digits of the 10,000th Fibonacci number (2,090) are:
First 20 : 33644764876431783266
Final 20 : 66073310059947366875
 
The digits of the 100,000th Fibonacci number (20,899) are:
First 20 : 25974069347221724166
Final 20 : 49895374653428746875
 
The digits of the 1,000,000th Fibonacci number (208,988) are:
First 20 : 19532821287077577316
Final 20 : 68996526838242546875
 
The digits of the 2^16th Fibonacci number (13,696) are:
First 20 : 73199214460290552832
Final 20 : 97270190955307463227
</pre>
<br>
===Lucas method===
{{trans|Go}}
Much quicker than the matrix exponentiation method taking about 23 seconds to process the 1 millionth Fibonacci number and around 32 minutes to reach the 10 millionth.
 
Apart from the 2^16th number, the extra credit is still out of reach using this approach.
<syntaxhighlight lang="wren">import "./big" for BigInt
import "./fmt" for Fmt
 
var lucas = Fn.new { |n|
var inner // recursive function
inner = Fn.new { |n|
if (n == BigInt.zero) return [BigInt.zero, BigInt.one]
var t = n >> 1
var res = inner.call(t)
var u = res[0]
var v = res[1]
t = n & BigInt.two
var q = t - BigInt.one
var r = BigInt.zero
u = u.square
v = v.square
t = n & BigInt.one
if (t == BigInt.one) {
t = u - q
t = BigInt.two * t
r = BigInt.three * v
return [u + v, r - t]
} else {
t = BigInt.three * u
r = v + q
r = BigInt.two * r
return [r - t, u + v]
}
}
var t = n >> 1
var res = inner.call(t)
var u = res[0]
var v = res[1]
var l = BigInt.two * v
l = l - u // Lucas function
t = n & BigInt.one
if (t == BigInt.one) {
var q = n & BigInt.two
q = q - BigInt.one
t = v * l
return t + q
}
return u * l
}
 
var n = BigInt.zero
var i = 10
while (i <= 1e7) {
n = BigInt.new(i)
var s = lucas.call(n).toString
Fmt.print("The digits of the $,sth Fibonacci number ($,s) are:", i, s.count)
if (s.count > 20) {
Fmt.print(" First 20 : $s", s[0...20])
if (s.count < 40) {
Fmt.print(" Final $-2d : $s", s.count-20, s[20..-1])
} else {
Fmt.print(" Final 20 : $s", s[s.count-20..-1])
}
} else {
Fmt.print(" All $-2d : $s", s.count, s)
}
System.print()
i = i * 10
}
n = BigInt.one << 16
var s = lucas.call(n).toString
Fmt.print("The digits of the 2^16th Fibonacci number ($,s) are:", s.count)
Fmt.print(" First 20 : $s", s[0...20])
Fmt.print(" Final 20 : $s", s[s.count-20..-1])</syntaxhighlight>
 
{{out}}
As matrix exponentiation method, plus:
<pre>
The digits of the 10,000,000th Fibonacci number (2,089,877) are:
First 20 : 11298343782253997603
Final 20 : 86998673686380546875
</pre>
<br>
===Fibmod method (embedded)===
{{trans|Go}}
{{libheader|Wren-gmp}}
Ridiculously fast (under 5ms) thanks to the stuff borrowed from Sidef and Julia combined with the speed of GMP.
<syntaxhighlight lang="wren">import "./gmp" for Mpz, Mpf
import "./fmt" for Fmt
 
var nd = 20 // number of digits to be displayed at each end
var pr = 128 // precision to be used
 
var one = Mpz.one
var two = Mpz.two
 
var fibmod = Fn.new { |n, nmod|
if (n < two) return n
var fibmods = {}
var f // recursive closure
f = Fn.new { |n|
if (n < two) return one
var ns = n.toString
var v = fibmods[ns]
if (v) return v
v = Mpz.zero
var k = n / two
var t = n & one
var u = Mpz.zero
if (t != one) {
t.set(f.call(k)).square
v.sub(k, one)
u.set(f.call(v)).square
} else {
t.set(f.call(k))
v.add(k, one)
v.set(f.call(v))
u.sub(k, one)
u.set(f.call(u)).mul(t)
t.mul(v)
}
t.add(u)
fibmods[ns] = t.rem(nmod)
return fibmods[ns]
}
var w = n - one
return f.call(w)
}
 
var binetApprox = Fn.new { |n|
var phi = Mpf.from(0.5, pr)
var ihp = phi.copy()
var root = Mpf.from(1.25, pr).sqrt
phi.add(root)
ihp.sub(root, ihp).neg
ihp.sub(phi, ihp).log
phi.log
var nn = Mpf.from(n, pr)
return phi.mul(nn).sub(ihp)
}
 
var firstFibDigits = Fn.new { |n, k|
var f = binetApprox.call(n)
var g = Mpf.new(pr)
g.div(f, Mpf.ln10(pr)).inc
g.floor.mul(Mpf.ln10(pr))
f.sub(g).exp
var p = Mpz.from(10).pow(k)
g.set(p)
f.mul(g)
return f.floor.toString[0...k]
}
 
var lastFibDigits = Fn.new { |n, k|
var p = Mpz.from(10).pow(k)
return fibmod.call(n, p).toString[0...k]
}
 
var start = System.clock
var n = Mpz.zero
var i = 10
while (i <= 1e7) {
n.set(i)
var nn = Mpz.from(i)
Fmt.print("\nThe digits of the $,r Fibonacci number are:", i)
var nd2 = nd
var nd3 = nd
// These need to be preset for i == 10 & i == 100
// as there is no way of deriving the total length of the string using this method.
if (i == 10) {
nd2 = 2
} else if (i == 100) {
nd3 = 1
}
var s1 = firstFibDigits.call(n, nd2)
if (s1.count < 20) {
Fmt.print(" All $-2d : $s", s1.count, s1)
} else {
Fmt.print(" First 20 : $s", s1)
var s2 = lastFibDigits.call(nn, nd3)
if (s2.count < 20) {
Fmt.print(" Final $-2d : $s", s2.count, s2)
} else {
Fmt.print(" Final 20 : $s", s2)
}
}
i = i * 10
}
var ord = ["th", "nd", "th"]
i = 0
for (p in [16, 32, 64]) {
n.lsh(one, p)
var nn = one << p
Fmt.print("\nThe digits of the 2^$d$s Fibonacci number are:", p, ord[i])
Fmt.print(" First $d : $s", nd, firstFibDigits.call(n, nd))
Fmt.print(" Final $d : $s", nd, lastFibDigits.call(nn, nd))
i = i + 1
}
System.print("\nTook %(System.clock-start) seconds.")</syntaxhighlight>
 
{{out}}
<pre>
The digits of the 10th Fibonacci number are:
All 2 : 55
 
The digits of the 100th Fibonacci number are:
First 20 : 35422484817926191507
Final 1 : 5
 
The digits of the 1,000th Fibonacci number are:
First 20 : 43466557686937456435
Final 20 : 76137795166849228875
 
The digits of the 10,000th Fibonacci number are:
First 20 : 33644764876431783266
Final 20 : 66073310059947366875
 
The digits of the 100,000th Fibonacci number are:
First 20 : 25974069347221724166
Final 20 : 49895374653428746875
 
The digits of the 1,000,000th Fibonacci number are:
First 20 : 19532821287077577316
Final 20 : 68996526838242546875
 
The digits of the 10,000,000th Fibonacci number are:
First 20 : 11298343782253997603
Final 20 : 86998673686380546875
 
The digits of the 2^16th Fibonacci number are:
First 20 : 73199214460290552832
Final 20 : 97270190955307463227
 
The digits of the 2^32nd Fibonacci number are:
First 20 : 61999319689381859818
Final 20 : 39623735538208076347
 
The digits of the 2^64th Fibonacci number are:
First 20 : 11175807536929528424
Final 20 : 17529800348089840187
 
Took 0.004516 seconds.
</pre>
9,482

edits