fibonacci_first_k_digits_in_base_b.sf 1.3 KB

12345678910111213141516171819202122232425262728293031323334
  1. #!/usr/bin/ruby
  2. # Daniel "Trizen" Șuteu
  3. # Date: 02 February 2020
  4. # https://github.com/trizen
  5. # Efficiently compute the first k digits (in base b) of the n-th Fibonacci number, using Binet's formula.
  6. # See also:
  7. # https://en.wikipedia.org/wiki/Fibonacci_number
  8. # https://rosettacode.org/wiki/Fibonacci_matrix-exponentiation
  9. # Based on the following identities (where b is the base):
  10. # f / exp(log(b)*floor(log(f) / log(b) + 1)) = exp(log(f) - log(b)*floor(log(f) / log(b) + 1))
  11. # = b^(-1 - floor(log(f^(1/log(b))))) * f
  12. # = exp(log(b)*(-1 - floor(log(f) / log(b))) + log(f))
  13. func f(n) {
  14. n*log((1+sqrt(5))/2) - log(5)/2
  15. }
  16. func nth_fib_first_k_digits(n,k,b=10) {
  17. int(b**(k-1) * exp(f(n) - log(b)*floor(f(n)/log(b))))
  18. }
  19. for k in (16, 32, 64) {
  20. printf("First 20 digits of F(2^#{k}) = %s (base 10) = %s (base 7)\n", nth_fib_first_k_digits(2**k, 20), nth_fib_first_k_digits(2**k, 20, 7).base(7))
  21. }
  22. __END__
  23. First 20 digits of F(2^16) = 73199214460290552832 (base 10) = 14145222604233421263 (base 7)
  24. First 20 digits of F(2^32) = 61999319689381859818 (base 10) = 63461236402304653504 (base 7)
  25. First 20 digits of F(2^64) = 11175807536929528424 (base 10) = 11322264102105626133 (base 7)