1

For a given value N I am trying to output the corresponding Fibonacci number F(N). My script doesn't seem to enter the recursive stage. fibonnaci($number) is not calling the subroutine. It is simply outputing "fibonacci(whatever number is inputted)".

Here is my code:

 #!/usr/bin/perl -w

use warnings;
use strict;


print "Please enter value of N: ";
my $number = <STDIN>;


chomp($number);

sub fibonacci
{

my $f;
if ( $number == 0 ) { # base case
      $f = 0;
   } elsif ( $number == 1 ) {
      $f = 1;
   } else {                                # recursive step
      $f = fibonacci( $number - 1 ) + fibonacci( $number - 2 );
   }

   return $f;

}


print "\nf($number) = fibonacci($number)\n";

Sample Output:

    Please enter value of N: 4

f(4) = fibonacci(4)
user1:~>recursiveFib.pl
Please enter value of N: 5

f(5) = fibonacci(5)
user1:~>recursiveFib.pl
Please enter value of N: 10

f(10) = fibonacci(10)
user1:~>

Not sure where I went wrong. Any help would be greatly appreciated.

chomp
  • 125
  • 9
  • You're not dealing with the subroutine parameter properly. You need a line like `my ($number) = @_;` as the first line in `fibonacci`. – ooga Nov 06 '14 at 03:40
  • I appreciate the response. I actually still get the same results even when I add that line. Any ideas? @ooga – chomp Nov 06 '14 at 03:45
  • It's your `print` line. Take the function call out of the quotes. `print "\n$number: ", fibonacci($number), "\n";` – ooga Nov 06 '14 at 03:52
  • 1
    You can use memoization to make it even faster . http://perldoc.perl.org/Memoize.html – xtreak Nov 06 '14 at 06:12

3 Answers3

3

You need to accept the function arguments properly and take the function call out of the quotes.

use warnings;
use strict;

sub fibonacci {
   my ($number) = @_;
   if ($number < 2) { # base case
      return $number;
   }
   return fibonacci($number-1) + fibonacci($number-2);
}

print "Please enter value of N: ";
my $number = <STDIN>;
chomp($number);
print "\n$number: ", fibonacci($number), "\n";

A more efficient but still recursive version:

sub fib_r {
  my ($n,$a,$b) = @_;
  if ($n <= 0) { return $a; }
  else         { return fib_r($n-1, $b, $a+$b); }
}

sub fib { fib_r($_[0], 0, 1); }  # pass initial values of a and b

print fib(10), "\n";
ooga
  • 15,423
  • 2
  • 20
  • 21
  • For your first example it is outputting wrong for me. For F(4) I get 3. F(5)=5, F(10)=55....@ooga – chomp Nov 06 '14 at 04:07
  • In my case if N=0 or N=1 the fibonacci number is supposed to be 1. That's where the mess up was. Fixed it. Thanks for the help! @ooga – chomp Nov 06 '14 at 04:40
3

Other answers have already mentioned the lack of taking an argument correctly to the fibonacci function, and that you can't interpolate a function call in the print string like that. Lately my favourite way to interpolate function calls into print strings is to use the ${\ ... } notation for embedding arbitrary expressions into strings:

print "f($number) = ${\ fibonacci($number) }\n";

Other techniques include separate arguments:

print "f($number) = ", fibonacci($number), "\n";

or a helper variable:

my $result = fibonacci($number);
print "f($number) = $result\n";

or even printf:

printf "f(%d) = %d\n", $number, fibonacci($number);

Of all these techniques I tend to prefer either of the first two, because they lead to putting the expressions "in-line" with the rest of the text string, whereas in the latter two they sit elsewhere, making it harder to see at a glance what gets printed where. Especially with printf's positional arguments, it can be easy to be "off-by-one" with a large number of arguments, and put everything in the wrong place.

LeoNerd
  • 8,344
  • 1
  • 29
  • 36
0

You are printing in wrong way. you just need to handle the return value. Also the way you are using Number in the sub is also not seems relevant. I have updated the and its working fine.

Also the values that you wanted to print is depend on the start up of the series. whether you want to start from 0 or 1. The series example start with 1 is 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, so if you put 10 you will get 55.

#!/usr/bin/perl -w

use warnings;
use strict;


print "Please enter value of N: ";
my $number = <STDIN>;


chomp($number);
my $result=fibonacci($number);

sub fibonacci
{
my $f =0;
if ($_[0] == 1 ) { # base case 
      $f = 1;
   } elsif ( $_[0] == 2 ) {
      $f = 1;
   } else {                                # recursive step
      $f= fibonacci( $_[0] - 1 ) + fibonacci( $_[0] - 2 );
    }
    return $f;
}


print "\nf($number) = $result\n";