How to compare two floating point values ​​in shell script

I needed to do a split in a shell script, and the best way:

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 ] did not help if [ $result1 -gt $result2 ]

Any idea how to do this?

+4
source share
3 answers

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 perform comparisons as well as calculations:

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

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

+6
source

note that you have to be careful when working with floating point numbers, and if you are checking for equality, you really want to solve some kind of precision and then compare with that. Sort of:

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

the reason is that with computers we are dealing with binary fractions with limited accuracy, and not with true mathematical realities. Limiting accuracy in bc with scale = 3 will have this effect.

I would advise against trying to do this in a shell script. This does not mean that you cannot do this, but you will have to brush off many small subcommands to execute complex bits and slow execution and, as a rule, pain for writing - you spend most of your time getting the shell to do what you want rather than writing the code you really want. Instead, switch to a more complex scripting language; 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 are dividing by the same value ($ total in your question), so the whole comparison can be performed against the numerators (var1 and var2) provided that $ total is positive

0
source

Sending a new answer as I cannot comment yet ...

@Norman Ramsey answer is not entirely accurate:

  • expr will perform an integer or string comparison, not a floating point comparison.
    This is what the man page says:

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

    Returns the results of an integer comparison if both arguments are integer; otherwise returns string comparison results using a locale-specific sort sequence.

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

  • bc works fine, but not always installed.


So another alternative uses perl -e :

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

    eg. perl -e 'print 8.9 < 10' - prints "1", and perl -e 'print 2>4' does not print anything.

  • And when used in an if :

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

0
source

Source: https://habr.com/ru/post/1308834/


All Articles