How to compare two floating point numbers in Bash?

2018-12-31 15:55发布

I am trying hard to compare two floating point numbers within a bash script. I have to variables, e.g.

let num1=3.17648e-22
let num2=1.5

Now, I just want do a simple comparison of these two numbers:

st=`echo "$num1 < $num2" | bc`
if [ $st -eq 1]; then
  echo -e "$num1 < $num2"
else
  echo -e "$num1 >= $num2"
fi

Unfortunately, I have some problems with the right treatment of the num1 which can be of the "e-format". :(

Any help, hints are welcome!

15条回答
余欢
2楼-- · 2018-12-31 16:09

More conveniently

This can be done more conveniently using Bash's numeric context:

if (( $(echo "$num1 > $num2" |bc -l) )); then
  …
fi

Explanation

Piping through the basic calculator command bc returns either 1 or 0.

The option -l is equivalent to --mathlib; it loads the standard math library.

Enclosing the whole expression between double parenthesis (( )) will translate these values to respectively true or false.

Please, ensure that the bc basic calculator package is installed.

查看更多
笑指拈花
3楼-- · 2018-12-31 16:10

Using bashj (https://sourceforge.net/projects/bashj/ ), a bash mutant with java support, you just write (and it IS easy to read):

#!/usr/bin/bashj

#!java
static int doubleCompare(double a,double b) {return((a>b) ? 1 : (a<b) ? -1 : 0);}

#!bashj
num1=3.17648e-22
num2=1.5
comp=j.doubleCompare($num1,$num2)
if [ $comp == 0 ] ; then echo "Equal" ; fi
if [ $comp == 1 ] ; then echo "$num1 > $num2" ; fi
if [ $comp == -1 ] ; then echo "$num2 > $num1" ; fi

Of course bashj bash/java hybridation offers much more...

查看更多
宁负流年不负卿
4楼-- · 2018-12-31 16:10

A solution supporting the scientific notation with both uppercase and lowercase exponents (e.g., 12.00e4):

if (( $(bc -l <<< "${value1/e/E} < ${value2/e/E}") ))
then
    echo "$value1 is less than $value2"
fi 
查看更多
后来的你喜欢了谁
5楼-- · 2018-12-31 16:12

Of course, if you don't need really floating-point arithmetic, just arithmetic on e.g. dollar values where there are always exactly two decimal digits, you might just drop the dot (effectively multiplying by 100) and compare the resulting integers.

if [[ ${num1/.} < ${num2/.} ]]; then
    ...

This obviously requires you to be sure that both values have the same number of decimal places.

查看更多
泛滥B
6楼-- · 2018-12-31 16:15

bash handles only integer maths but you can use bc command as follows:

$ num1=3.17648E-22
$ num2=1.5
$ echo $num1'>'$num2 | bc -l
0
$ echo $num2'>'$num1 | bc -l
1

Note that exponent sign must be uppercase

查看更多
萌妹纸的霸气范
7楼-- · 2018-12-31 16:16

you can use awk combined with a bash if condition, awk will print 1 or 0 and those will be interpreted by if clause with true or false.

if (( $(awk 'BEGIN {print ("'$d1'" >= "'$d2'")}') )); then
    echo "yes"
else 
    echo "no"
fi
查看更多
登录 后发表回答