How to compare to floating point number in a shell script

Bash does not understand floating point arithmetic. It treats numbers containing a decimal point as strings.

Use awk or bc instead.

#!/bin/bash

min=12.45
val=10.35

if [ 1 -eq "$(echo "${val} < ${min}" | bc)" ]
then  
    min=${val}
fi

echo "$min"

If you intend to do a lot of math operations, it's probably better to rely on python or perl.


You can use package num-utils for simple manipulations...

For more serious maths, see this link... It describes several options, eg.

  • R / Rscript (GNU R statistical computation and graphics system)
  • octave (mostly Matlab compatible)
  • bc (The GNU bc arbitrary precision calculator language)

An example of numprocess

echo "123.456" | numprocess /+33.267,%2.33777/
# 67.0395291239087  

A programs for dealing with numbers from the command line

The 'num-utils' are a set of programs for dealing with numbers from the
Unix command line. Much like the other Unix command line utilities like
grep, awk, sort, cut, etc. these utilities work on data from both
standard in and data from files.

Includes these programs:
 * numaverage: A program for calculating the average of numbers.
 * numbound: Finds the boundary numbers (min and max) of input.
 * numinterval: Shows the numeric intervals between each number in a sequence.
 * numnormalize: Normalizes a set of numbers between 0 and 1 by default.
 * numgrep: Like normal grep, but for sets of numbers.
 * numprocess: Do mathematical operations on numbers.
 * numsum: Add up all the numbers.
 * numrandom: Generate a random number from a given expression.
 * numrange: Generate a set of numbers in a range expression.
 * numround: Round each number according to its value.

Here is a bash hack...It adds leading 0's to the integer to make a string left-to-right comparison meaningful. This particular piece of code requires that both min and val actually have a decimal point and at least one decimal digit.

min=12.45
val=10.35

MIN=0; VAL=1 # named array indexes, for clarity
IFS=.; tmp=($min $val); unset IFS 
tmp=($(printf -- "%09d.%s\n" ${tmp[@]}))
[[ ${tmp[VAL]} < ${tmp[MIN]} ]] && min=$val
echo min=$min

output:

min=10.35

For simple calculations on floating point numbers (+-*/ and comparisons), you can use awk.

min=$(echo 12.45 10.35 | awk '{if ($1 < $2) print $1; else print $2}')

Or, if you have ksh93 or zsh (not bash), you can use your shell's built-in arithmetic, which supports floating point numbers.

if ((min>val)); then ((val=min)); fi

For more advanced floating point calculations, look up bc. It actually works on arbitrary-precision fixpoint numbers.

To work on tables of numbers, look up R (example).