37

I know it's really stupid question, but I don't know how to do this in bash:

20 / 30 * 100

It should be 66.67 but expr is saying 0, because it doesn't support float. What command in Linux can replace expr and do this equalation?

lennon310
  • 12,503
  • 11
  • 43
  • 61
lauriys
  • 4,652
  • 7
  • 32
  • 40

6 Answers6

39

bc will do this for you, but the order is important.

> echo "scale = 2; 20 * 100 / 30" | bc
66.66
> echo "scale = 2; 20 / 30 * 100" | bc
66.00

or, for your specific case:

> export ach_gs=2
> export ach_gs_max=3
> x=$(echo "scale = 2; $ach_gs * 100 / $ach_gs_max" | bc)
> echo $x
66.66

Whatever method you choose, this is ripe for inclusion as a function to make your life easier:

#!/bin/bash
function pct () {
    echo "scale = $3; $1 * 100 / $2" | bc
}

x=$(pct 2 3 2) ; echo $x # gives 66.66
x=$(pct 1 6 0) ; echo $x # gives 16
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • but i want to do this in script, the full line is : $ach_gs / $ach_gs_max * 100 – lauriys Aug 10 '09 at 09:52
  • @maxorq: You might note that in all examples others have given, the multiplication is done first. This is a scientific computing thing -- since we know there are more digits available to the left of the decimal place than to the right, multiplication goes first to minimize loss of precision due to rounding. – Conspicuous Compiler Aug 10 '09 at 10:00
15

just do it in awk

# awk 'BEGIN{print 20 / 30 * 100}'
66.6667

save it to variable

# result=$(awk 'BEGIN{print 20 / 30 * 100}')
# echo $result
66.6667
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
15

I generally use perl:

perl -e 'print 10 / 3'
pgl
  • 7,551
  • 2
  • 23
  • 31
  • it must be a very basic perl issue, but this command only displays a blank line on my system. `perl -e 'print "hello world"'` does not work either. But `perl -e 'print "hello world\n"'` does work as expected. – Sébastien May 31 '14 at 11:55
  • 2
    I'm afraid I can't help. All I can suggest is to add `, "\n"` to the end of the expression: `perl -e 'print 10 / 3, "\n"'` – pgl Jun 02 '14 at 10:30
  • Thanks, this workaround works. (and your command works 'as-is' on another linux environment) – Sébastien Jun 02 '14 at 13:54
  • For the Pythonistas among us: `python -c "print 10.0/3.0"` – emazzotta Dec 18 '15 at 14:17
7

As reported in the bash man page:

The shell allows arithmetic expressions to be evaluated, under certain circumstances...Evaluation is done in fixed-width integers with no check for overflow, though division by 0 is trapped and flagged as an error.

You can multiply by 100 earlier to get a better, partial result:

let j=20*100/30
echo $j

66

Or by a higher multiple of 10, and imagine the decimal place where it belongs:

let j=20*10000/30
echo $j

66666

Conspicuous Compiler
  • 6,403
  • 1
  • 40
  • 52
  • It might help if you posted the actual command line you used. (I'm guessing you used more zeroes than I did.) I executed the commands above before I posted, and got the results given. Please try those first. – Conspicuous Compiler Aug 10 '09 at 09:58
  • Huh, odd, I don't remember putting spaces in there originally. Anyhow, try removing your spaces and repeat. I edited my post to remove the problematic whitespace. – Conspicuous Compiler Aug 10 '09 at 10:01
  • 1
    The question was to deal with floating point number; bash "let" returns integer – HidekiAI Jul 25 '13 at 14:27
  • Yes, HidekiAI, that's why I say to "imagine the decimal place where it belongs". The returned result 66666 represents an actual value of 66666 * 10^-3. – Conspicuous Compiler Jul 25 '13 at 17:10
5
> echo "20 / 30 * 100" | bc -l
66.66666666666666666600

This is a simplification of the answer by paxdiablo. The -l sets the scale (number of digits after the decimal) to 20. It also loads a math library with trig functions and other things.

bjc
  • 1,201
  • 12
  • 10
0

Another obvious option:

python -c "print(20 / 30 * 100)"

assuming you are using Python 3. Otherwise, use python3.

Jules G.M.
  • 3,624
  • 1
  • 21
  • 35