fact()
{
if [ $1 -eq 1 ]
then
return 1
else
y=`expr $1 - 1`
fact $y
b=$(($1 * $?))
return $b
fi
}
echo "enter"
read n
fact $n
echo "$?"
This is a program to find the factorial of a number. The output is correct up to 5. The output of 6 is giving as 208 but the correct answer is 720. What's causing this error?
Interestingly, the program works as expected using dash, it only fails using bash. So it looks like this is a bashism.
Just add the line
at the top of the program and it works!
What you are seeing is the wraparound of function return values at 256.
720 mod 256
is208
(256 + 256 + 208 = 720
).My advice, if you must use a shell function, is to do:
This uses standard output for returning values, rather than the return code.
Or, even better, use the right tools for the job:
I'd love to see a
bash
-only solution calculate the factorial of 500 :-)Bash scripts and Bash functions return values are intended to be returned codes, and thus limited with the values they are capable of returning. You shouldn't depend on values grater then 127 (typically values that are grater then 127 - up to 255 - are used to indicate signals received).
The lines
expect use the return code
$?
offact
, and this code can't be grater then 255.The Bash way of returning values is printing them, and parsing or evaluating this output.
The bourne shell cant store alot in $? (exit code). limit is 255. heres an alternative way
Function return values can only go up to 255:
Produces:
return
is likeexit
andexit
can only take values up to 255 (http://www.unix.org/whitepapers/shdiffs.html).One alternative is to switch to an iterative suggestion, as described in another answer. Alternatively you can use echo and capture the recursive output that way: