2010-08-03 77 views

Respuesta

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 
4
echo 500 | dc -e '?[q]sQ[d1=Qd1-lFx*]dsFxp' 
+1

1 agradable, aunque no tengo ni idea de por qué funciona;) –

+0

Este utiliza un programa externo con una sintaxis arcano para realizar los cálculos. –

+1

@luther, las herramientas externas dedicadas como bc, dc pueden calcular números más grandes. Por lo tanto, son la herramienta más adecuada para el trabajo. Hay un límite para lo que Bash puede calcular para factoriales más grandes. – ghostdog74

4

10! en bash:

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

o aquí en un paso a paso la moda:

$ 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 
+0

hay un límite para lo que bash puede hacer. se rompe para números más grandes.Tal vez usted tiene una forma de producir los mismos resultados para factorial de, por ejemplo, 500, con bash? – ghostdog74

+0

Estoy bien con cualquiera que use herramientas externas para calcular lo que necesitan. Pero el OP preguntó cómo hacer esto en bash, así que pensé que era muy probable que se tratara de un ejercicio de "bash para programación general", capítulo "cómo hacer loop in bash". –

9

Usted no lo hagas en bash. Las personas inteligentes no intentan talar árboles con un pez, así que mi consejo es probar y usar la herramienta adecuada para el trabajo.

Se puede utilizar, por ejemplo, bc hacerlo así:

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 
12201368259911100687
45373153881997605496447502203281863013616477148203584163378722078177 
20048078520515932928547790757193933060377296085908627042917454788242 
49127263443056701732707694610628023104526442188787894657547771498634 
94367781037644274033827365397471386477878495438489595537537990423241 
06127132698432774571554630997720278101456108118837370953101635632443 
29870295638966289116589747695720879269288712817800702651745077684107 
19624390394322536422605234945850129918571501248706961568141625359056 
69342381300885624924689156412677565448188650659384795177536089400574 
52389403357984763639449053130623237490664450488246650759467358620746 
37925184200459369692981022263971952597190945217823331756934581508552 
33282076282002340262690789834245171200620771464097945611612762914595 
12372299133401695523638509428855920187274337951730145863575708283557 
80158735432768888680120399882384702151467605445407663535984174430480 
12893831389688163948746965881750450692636533817505547812864000000000 
00000000000000000000000000000000000000000000000000000000000000000000 
00000000000000000000000000000000000000000000000 
+3

de acuerdo. OTOH Me encontré un par de veces en un bosque con un martillo, un cuchillo de mantequilla y una caja ocupada. Así que esto debería etiquetarse como "entrenamiento de supervivencia" –

13
seq -s "*" 1 500 |bc 
+1

Y, por cierto. esto no funciona en Mac OSX ni en ningún otro sistema que no incluya GNU coreutils (que forma parte de) –

+0

y luego use jot en Mac OS. Si hay otro sistema – ghostdog74

2

Aquí es una función recursiva en Bash:

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

Por supuesto que es bastante lento y limitado.

1

Hay una serie de ejemplos instructivos on Rosetta Code.

Aquí hay una que encontré particularmente útil:

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

casi completamente de acuerdo con Vitalii Fedorenko, me gustaría paxdiablo sugiere utilizar bc, aquí está el código de Vitalii Fedorenko, pero modificado para utilizar 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 

Este método es mejor porque bc le permite utilizar cadenas, en lugar de números enteros, por lo que es posible que usted pueda calcular los números mucho más grandes.

Disculpe si no he usado tr correctamente, no estoy muy familiarizado con él.

0
seq -s* `dd`|bc 

Creo que esta es la forma más rápida de llevar a cabo la tarea.

0

Se puede utilizar:

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

en un mac

Cuestiones relacionadas