4

I had to do a division in shell script and the best way was:

result1=`echo "scale=3; ($var1 / $total) * 100"| bc -l`
result2=`echo "scale=3; ($var2 / $total) * 100"| bc -l`

but I want to compare the values of $result1 and $result2

Using if test $result1 -lt $result2 or if [ $result1 -gt $result2 ] didn't work :(

Any idea how to do that?

3 Answers 3

6

You can compare floating-point numbers using expr(1):

: nr@yorkie 3724 ; expr 3.1 '<' 3.3
1
: nr@yorkie 3725 ; expr 3.1 '<' 3.09
0

You can also have bc do the comparisons as well as the calculations:

if [ "$(echo $result1 '<' $result2 | bc -l)" -eq 1 ];then ... fi

Finally, ksh93 can do arithmetic evaluation $(($result1 < $result2)) with floating-point numbers, although bash cannot.

Sign up to request clarification or add additional context in comments.

1 Comment

` if [ "$(echo $resutl1 '>' $result2 | bc -l)" -eq 1 ];then ` works for me :)
0

note that you've gotta be a bit careful when dealing with floating point numbers and if you are testing for equality you really want to decide on some precision and then compare using that. Something like:

if (abs(x1-x2) < 0.0001) then equal # pseudo-code

the reason being that with computers we're dealing with limited-precision binary fractions not true mathematical reals. Limiting the precision in bc with the scale=3 will have this effect.

I'd also advise against trying to do this stuff in shell script. It's not that you can't do it but you'll have to fork off lots of little sub commands to do the tricky bits and that's slow to execute and generally a pain to write - you spend most of your time trying to get the shell to do what you want rather than writing the code you really want. Drop into a more sophisticated scripting language instead; my language of choice is perl but there are others. like this...

echo $var1 $var2 $total | perl -ne 'my ($var1, $var2, $tot) = split /\s+/; if ($var1/$tot == $var2/$tot) { print "equal\n"; }'

also note that you're dividing by the same value ($total in your question) so the whole comparison can be done against the numerators (var1 and var2) provided $total is positive

Comments

0

Posting a new answer since I cannot yet comment...

@Norman Ramsey's answer is not quite accurate:

  • expr will perform an integer or string comparison, not a floating-point comparison.
    Here's what the man page says:

    expr1 {=, >, >=, <, <=, !=} expr2

    Return the results of integer comparison if both arguments are integers; otherwise, returns the results of string comparison using the locale-specific collation sequence.

    (just try expr 8.9 '<' 10 and get 0 where it should be 1).

  • bcworks great, but isn't always installed.


So another alternative is using perl -e:

  • perl -e 'print expression' will print 1 if expression is true and nothing (empty string) otherwise.

    e.g. perl -e 'print 8.9 < 10' - prints "1", while perl -e 'print 2>4' prints nothing.

  • And when used in if statement:

    if [ $(perl -e "print $result1 < $result2") ];then ... fi

Comments

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.