How to use expr on float?
Asked Answered
C

7

39

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?

Carmencita answered 10/8, 2009 at 9:48 Comment(2)
Sorry, mea culpa, mea maxima!Polymeric
for maths operations, try to use bc or awk , not bash or exprArietta
A
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

Antihelix answered 10/8, 2009 at 9:55 Comment(4)
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.Antihelix
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.Antihelix
The question was to deal with floating point number; bash "let" returns integerTriserial
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.Antihelix
V
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
Veldaveleda answered 10/8, 2009 at 9:52 Comment(2)
but i want to do this in script, the full line is : $ach_gs / $ach_gs_max * 100Carmencita
@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.Antihelix
A
17

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
Arietta answered 10/8, 2009 at 10:17 Comment(2)
This answer is very awkward.Oblast
Good answer. There's a bigger change a system has awk than bc.Pascha
E
15

I generally use perl:

perl -e 'print 10 / 3'
Edomite answered 12/8, 2009 at 15:19 Comment(4)
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.Whop
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"'Edomite
Thanks, this workaround works. (and your command works 'as-is' on another linux environment)Whop
For the Pythonistas among us: python -c "print 10.0/3.0"Changeful
A
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

Antihelix answered 10/8, 2009 at 9:55 Comment(4)
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.Antihelix
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.Antihelix
The question was to deal with floating point number; bash "let" returns integerTriserial
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.Antihelix
Z
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.

Zachariahzacharias answered 14/9, 2016 at 9:13 Comment(0)
H
0

Another obvious option:

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

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

Hexad answered 31/1, 2020 at 21:52 Comment(0)
H
0

expr doesn;t support float,
You can make a simple c calculator and just use,

./mycal 22 / 7.0

Handgun answered 15/6 at 16:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.