inverse_of_fibonacci.pl 1.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. #!/usr/bin/perl
  2. # Find the position of a Fibonacci number in the Fibonacci sequence.
  3. # See also:
  4. # https://en.wikipedia.org/wiki/Fibonacci_number#Recognizing_Fibonacci_numbers
  5. use 5.020;
  6. use strict;
  7. use warnings;
  8. use experimental qw(signatures);
  9. use Math::AnyNum qw(:overload fibonacci is_square isqrt phi round);
  10. sub fibonacci_inverse ($n) {
  11. my $m = 5 * $n * $n;
  12. if (is_square($m - 4)) {
  13. $m = isqrt($m - 4);
  14. }
  15. elsif (is_square($m + 4)) {
  16. $m = isqrt($m + 4);
  17. }
  18. else {
  19. return -1; # not a Fibonacci number
  20. }
  21. round(log(($n * sqrt(5) + $m) / 2) / log(phi));
  22. }
  23. foreach my $n(3..20) {
  24. my $fib = fibonacci($n);
  25. my $index = fibonacci_inverse($fib);
  26. die "error: $index != $n" if ($index != $n);
  27. say "F($index) = $fib";
  28. }
  29. die "error" if fibonacci_inverse(fibonacci(1000)) != 1000;
  30. die "error" if fibonacci_inverse(fibonacci(1001)) != 1001;
  31. die "error" if fibonacci_inverse(fibonacci(1002)) != 1002;
  32. die "error" if fibonacci_inverse(fibonacci(1003)) != 1003;