-1

Trying to translate:

What is a basic, elegant and fast way, to write factorial in Bash/in a shell script, purely. (Code) Please make suggestions. (Code)

Tem outra alternativa mais básica/elegante/rápida de como fazer em poucas linhas de código uma maneira de calcular um número fatorial em BASH (Shell Script) puro.

Ex.: 5! = 5*4*3*2*1 = 120

Essa é minha sugestão:

num=5
echo $(($(eval echo {$num..1} | sed 's/ /*/g')))
user unknown
  • 10,267
  • 3
  • 35
  • 58
  • 1
    In English, per favore. – jasonwryan Feb 26 '18 at 01:46
  • I can't read most of those words, but if you're looking for a factorial, try [this](https://unix.stackexchange.com/questions/409491/factorial-of-certain-numbers-yield-negative-values) or [this](https://unix.stackexchange.com/questions/44226/bc-doesnt-support-log-and-factorial-calculation) or [this](https://unix.stackexchange.com/questions/45909/do-shells-support-recursion) or [this](https://unix.stackexchange.com/questions/41957/how-to-define-a-bc-function-for-later-use) – Jeff Schaller Feb 26 '18 at 01:47
  • I will just mention that Stack Overflow in Spanish is a thing: https://es.stackoverflow.com/ – dhag Feb 26 '18 at 03:24
  • 1
    @dhag This is Portuguese, not Spanish – Fox Feb 26 '18 at 03:51
  • 1
    @Fox: Whoops. Thanks. Perhaps https://pt.stackoverflow.com/ would be an idea, then. – dhag Feb 26 '18 at 05:31

1 Answers1

2

This works without eval:

prod=$(echo {1..5}* 1); echo $((prod))

Here is a bash function, which takes an parameter, what isn't possible in the above solution:

fak () 
{ 
    echo $(($(seq -s'*' 1 $1)))
}

As cas pointed out in the comments, the Shell is limited to 64 bits, for bigger results, bc is worth a try, but that isn't puro, is it? Well - that argument count's for seq too; it's an external program.

echo {1..30}* 1 | bc
user unknown
  • 10,267
  • 3
  • 35
  • 58
  • +1 for the `{1..5}* 1`, but it's probably better to pipe into `bc` rather than use bash's built-in arithmetic. `bc` can work with integers of any arbitrary precision, while shell has a maxint value (determined mostly by cpu architecture it was compiled on - e.g. 64 bit int on a 64 bit cpu). For example, `prod=$(echo {1..30}* 1); echo $((prod))` prints `-8764578968847253504` (clearly wrong), while `echo {1..30}* 1 | bc` prints `265252859812191058636308480000000` (presumably correct). – cas Feb 26 '18 at 02:11
  • Yes, bc reaches far wider, while not arbitrary wide - test `echo "9^9^9 | bc"`. And afaik, bash calculated with 64 bits when I still used a 32bit PC, but I'm not 100% sure about that. I don't speak Brazilian/Portuguese, but "em BASH (Shell Script) puro" sounds much like "in purely Bash" doesn't it? (I updated the translation). And the example 5! didn't look that ambitious, too. :) – user unknown Feb 26 '18 at 03:08
  • the `bc` docs & man page say "arbitrary" so that's what i copied :) – cas Feb 26 '18 at 03:13
  • BTW, piping into `bc` works for at least up to `99999!`. That took about 5 minutes to run on my machine, which was boring enough to discourage me from trying larger numbers. – cas Feb 26 '18 at 03:22
  • afaik echo "8^8^8 | bc" fails too, but "7^7^7 | bc" should work. :) – user unknown Feb 26 '18 at 03:28
  • 1
    `{1..5}* 1` looks cool until you happen to have a file starting with one of these digits in the current directory: and `bc` responds with `(standard_in) 1: syntax error` – arielf Sep 26 '18 at 18:48