13

In shell scripting how to find factorial of a number?

14 Answers 14

18
seq -s "*" 1 500 |bc
Sign up to request clarification or add additional context in comments.

2 Comments

And btw. this does not work on Mac OSX or any other system that does not come with the GNU coreutils (which seq is a part of)
then use jot on Mac OS. If any other system
13

You don't do it in bash. Intelligent people don't try to cut down trees with a fish, so my advice is to try and use the right tool for the job.

You can use, for example, bc to do it thus:

pax> echo 'define f(x) {if (x>1){return x*f(x-1)};return 1}
           f(6)' | bc
720
pax> echo 'define f(x) {if (x>1){return x*f(x-1)};return 1}
           f(500)' | BC_LINE_LENGTH=99999 bc
12201368259911100687012387854230469262535743428031928421924135883858
45373153881997605496447502203281863013616477148203584163378722078177
20048078520515932928547790757193933060377296085908627042917454788242
49127263443056701732707694610628023104526442188787894657547771498634
94367781037644274033827365397471386477878495438489595537537990423241
06127132698432774571554630997720278101456108118837370953101635632443
29870295638966289116589747695720879269288712817800702651745077684107
19624390394322536422605234945850129918571501248706961568141625359056
69342381300885624924689156412677565448188650659384795177536089400574
52389403357984763639449053130623237490664450488246650759467358620746
37925184200459369692981022263971952597190945217823331756934581508552
33282076282002340262690789834245171200620771464097945611612762914595
12372299133401695523638509428855920187274337951730145863575708283557
80158735432768888680120399882384702151467605445407663535984174430480
12893831389688163948746965881750450692636533817505547812864000000000
00000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000

2 Comments

Agreed. OTOH I found myself a couple of time in a forest with a hammer, a butter knife and busybox. So this should be tagged as "survival training"
@paxdiablo : Totally agree. I must admit I haven’t search much with bc. I assume that because it doesn’t have this function natively defined it wasn’t the right tool. The fact is the good old recursive function to do it is one of the first example given in the man page of bc. I guess bc comes with a very few functions defined to keep a little memory footprint.
7
#!/bin/bash
counter=$1 #first argument
factorial=1
while [ $counter -gt 0 ] #while counter > 0
do
   factorial=$(( $factorial * $counter ))
   counter=$(( $counter - 1 ))
done
echo $factorial

Comments

5
echo 500 | dc -e '?[q]sQ[d1=Qd1-lFx*]dsFxp'

4 Comments

This uses an external program with an arcane syntax to perform the computations.
@luther, external dedicated tools like bc, dc are able to calculate bigger numbers. Therefore, they are most appropriate tool for the job. There's a limit to what bash can calculate for bigger factorials.
@gd: I was just informing Felix what was happening there. Understanding bash does not mean understanding the above statement.
This would be far more useful if you explained how it works :-)
5

10! in bash:

f=1; for k in {1..10}; do f=$[$k * $f] ; done; echo $f

or here in a step by step fashion:

$ t=$(echo {1..10})
$ echo $t
1 2 3 4 5 6 7 8 9 10
$ t=${t// /*}
$ echo $t
1*2*3*4*5*6*7*8*9*10
$ echo $[$t]
3628800

3 Comments

there's a limit for what bash can do. it breaks for bigger numbers. Maybe you have a way of producing the same results for factorial of say, for example, 500, with bash ?
I'm fine with anybody using external tools to compute what they need. But the OP asked how to do this in bash, so I figured this was most likely an exercise in "bash for general programming", chapter "how to loop in bash".
$ f=1; for k in {1..30}; do f=$[$k * $f] ; done; echo $f -8764578968847253504
4
echo Enter Number

read num
fact=1
for ((i=1;i<=num;i++))
do
fact=$(($fact*$i))
done
echo $fact

Comments

3

Here is a recursive function in Bash:

factorial () { 
    if (($1 == 1))
    then
        echo 1
        return
    else
        echo $(( $( factorial $(($1 - 1)) ) * $1 ))
    fi
}

Of course it's quite slow and limited.

Comments

2

There are a number of instructive examples on Rosetta Code.

Here's one I found particularly useful:

function factorial {
  typeset n=$1
  (( n < 2 )) && echo 1 && return
  echo $(( n * $(factorial $((n-1))) ))
}

Comments

2
seq -s* `dd`|bc

I believe this is the shortest way of accomplishing the task.

1 Comment

I had to simple-quote the asterisk to make it work. For dc: { echo -n $(seq 52) && echo -n ' ' && for i in $(seq 51); do echo -n '* '; done && echo -e "p"; } | dc −−−− The results: bc: 52! = 80658175170943878571660636856403766975289505440883277824000000000000 Gnumeric: 52! = 80658175170943878570206523603817122958308647184520011580139995398144 dc: 52! = 80658175170943878571660636856403766975289505440883277824000000000000
1

Please use this script to find factorial in Bash,

#!/bin/bash

num=$1
fact=1
for((i=1; i<=$num; i++))
do
        let fact=fact*i
done

echo "Factorial is $fact"

1 Comment

Can you elaborate on what exactly you're doing?
0

You have to use loop, see this link: http://ubuntuforums.org/showthread.php?t=1349272

Comments

0

I almost completely agree with Vitalii Fedorenko, I would just like paxdiablo suggests use bc, here's the code from Vitalii Fedorenko but modified to use bc.

#!/bin/bash
counter=$1
output=1
while [ $counter -gt 1 ] #while counter > 1 (x*1=x)
do
        output=$(echo "$output * $counter" | bc)
        counter=$(($counter - 1))
done
#remove newlines and '\' from output
output=$(echo "$output" | tr -d '\' | tr -d '\n')
echo "$output"
exit

This method is better because bc allows you to use strings, instead of integers, making it possible for you to calculate much bigger numbers.

I apologize if I haven't used tr correctly, I am not very familiar with it.

Comments

0

You can use:

seq -s "*" 1 10 | sed 's/*$//g' |bc

on a mac

1 Comment

sed command is useless! As -s stand for separator, seq won't add a star * after last element.
0
#!/bin/bash
#Naive factorial solution
function factorial() {
    if [[ $1 == 1 ]]; then
        echo 1
    elif [[ $1 == 0 ]]; then
        echo 1
    else
        echo $(( $(factorial $(( $1 - 1 ))) * $1 ))
    fi
}

for index in {1..21}
do
    echo "$index! == $(factorial $index)"
done

Output

1! == 1
2! == 2
3! == 6
4! == 24
5! == 120
6! == 720
7! == 5040
8! == 40320
9! == 362880
10! == 3628800
11! == 39916800
12! == 479001600
13! == 6227020800
14! == 87178291200
15! == 1307674368000
16! == 20922789888000
17! == 355687428096000
18! == 6402373705728000
19! == 121645100408832000
20! == 2432902008176640000
21! == -4249290049419214848

1 Comment

Same, without amy loop: buildFactorArray () { local varname=factors expr; [[ $1 == -v ]] && varname=$2 && shift 2; local qte=${1:-12}; local -ia "qte=({2..$qte})"; printf -v expr "${varname}[%d] = ${varname}[%d-1] * %d," ${qte[@]//*/& & &}; ((${varname}[1]=1,${expr}0));} Try: buildFactorArray -v myArray 21; declare -p myArray

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.