Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I compare two floating point numbers in Bash?

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.

Caveat: Exponential notation should be written as *10^; not E, nor e.

For example:

$ echo "1*10^3==1000" |bc
1

Whereas

$ echo "1E3==1000" |bc
0

Strategies to overcome this bc limitation are discussed here.


Bash handles only integer maths, but you can use the 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 the exponent sign must be uppercase.


It's better to use AWK for noninteger mathematics. You can use this Bash utility function:

numCompare() {
   awk -v n1="$1" -v n2="$2" 'BEGIN {printf "%s " (n1<n2?"<":">=") " %s\n", n1, n2}'
}

And call it as:

numCompare 5.65 3.14e-22
5.65 >= 3.14e-22

numCompare 5.65e-23 3.14e-22
5.65e-23 < 3.14e-22

numCompare 3.145678 3.145679
3.145678 < 3.145679

A pure Bash solution for comparing floats without exponential notation, leading or trailing zeros:

if [ ${FOO%.*} -eq ${BAR%.*} ] && [ ${FOO#*.} \> ${BAR#*.} ] || [ ${FOO%.*} -gt ${BAR%.*} ]; then
  echo "${FOO} > ${BAR}";
else
  echo "${FOO} <= ${BAR}";
fi

The order of logical operators matters. Integer parts are compared as numbers and fractional parts are intentionally compared as strings. Variables are split into integer and fractional parts using this method.

It won't compare floats with integers (without dot).


You can use AWK combined with a Bash if condition:

if awk "BEGIN {exit !($d1 >= $d2)}"; then
    echo "yes"
else
    echo "no"
fi