## How can I calculate with floating point numbers instead of just integers?

BASH's builtin arithmetic uses integers only:

$ echo "$((10 / 3))" 3

For most operations involving floating-point numbers, an external program must be used, e.g. `bc`, AWK or `dc`:

$ echo 'scale=3; 10/3' | bc 3.333

The "scale=3" command notifies `bc` that three digits of precision after the decimal point are required.

Same example with `dc` (reverse polish calculator, lighter than `bc`):

$ echo '3 k 10 3 / p' | dc 3.333

`k` sets the precision to 3, and `p` prints the value of the top of the stack with a newline. The stack is not altered, though.

If you are trying to compare floating point numbers (less-than or greater-than), and you have GNU `bc`, you can do this:

# Bash if (( $(bc <<<'1.4 < 2.5') )); then echo '1.4 is less than 2.5.' fi

However, *x < y* is not supported by all versions of `bc`:

# HP-UX 10.20. imadev:~$ bc <<<'1 < 2' syntax error on line 1,

If you want to be portable, you need something more subtle:

# POSIX case $(echo '1.4 - 2.5' | bc) in -*) echo '1.4 is less than 2.5';; esac

This example subtracts 2.5 from 1.4, and checks the sign of the result. If it is negative, the first number is less than the second. We aren't actually treating `bc`'s output as a number; we're treating it as a string, and only looking at the first character.

Legacy (Bourne) version:

# Bourne case "`echo "1.4 - 2.5" | bc`" in -*) echo "1.4 is less than 2.5";; esac

AWK can be used for calculations, too:

$ awk 'BEGIN {printf "%.3f\n", 10 / 3}' 3.333

There is a subtle but important difference between the `bc` and the `awk` solution here: `bc` reads commands and expressions from *standard input*. `awk` on the other hand evaluates the expression as *part of the program*. Expressions on standard input are *not* evaluated, i.e. `echo 10/3 | awk '{print $0}'` will print `10/3` instead of the evaluated result of the expression.

ksh93 and zsh have support for floating point in shell arithmetic. Newer versions of ksh93 additionally have support for all C99 math.h functions `sin()` or `cos()` as well as user-defined math functions callable using C syntax. So many of these calculations can be done natively in ksh:

# ksh93/zsh $ LC_NUMERIC=C; echo "$((3.00000000000/7))" 0.428571428571428571

(ksh93 is sensitive to locale. A dotted decimal used in locales where the decimal separator character is not *dot* will fail, like in German, Spanish, French locales...).

Comparing two floating-point numbers for *equality* is potentially an unwise thing to do. Similar calculations that are mathematically equivalent and which you would expect to give the same result on paper may give ever-so-slightly-different floating-point numeric results due to rounding/truncation and other issues. If you wish to determine whether two floating-point numbers are "the same", you may either:

- Round them both to a desired level of precision, and then compare the rounded results for equality; or
Subtract one from the other and compare the absolute value of the difference against an

*epsilon*value of your choice.Be sure to output adequate precision to fully express the actual value. Ideally, use hex float literals, which are supported by Bash.

$ ksh -c 'LC_NUMERIC=C printf "%-20s %f %.20f %a\n" "error accumulation:" .1+.1+.1+.1+.1+.1+.1+.1+.1+.1{,,} constant: 1.0{,,}' error accumulation: 1.000000 1.00000000000000000011 0x1.0000000000000002000000000000p+0 constant: 1.000000 1.00000000000000000000 0x1.0000000000000000000000000000p+0

One of the very few things that Bash actually *can* do with floating-point numbers is round them, using `printf`:

# Bash 3.1 # See if a and b are close to each other. # Round each one to two decimal places and compare results as strings. a=3.002 b=2.998 printf -v a1 %.2f "$a" printf -v b1 %.2f "$b" if [[ $a1 = "$b1" ]]; then echo 'a and b are roughly the same' fi

Many problems that look like floating point arithmetic can in fact be solved using integers only, and thus do not require these tools -- e.g., problems dealing with rational numbers. For example, to check whether two numbers `x` and `y` are in a ratio of 4:3 or 16:9 you may use something along these lines:

# Bash # Variables x and y are integers if (( (x * 9 - y * 16) == 0 )) ; then echo 16:9. elif (( (x * 3 - y * 4) == 0 )) ; then echo 4:3. else echo 'Neither 16:9 nor 4:3.' fi

A more elaborate test could tell if the ratio is closest to 4:3 or 16:9 without using floating point arithmetic. Note that this very simple example that apparently involves floating point numbers and division is solved with integers and no division. If possible, it's usually more efficient to convert your problem to integer arithmetic than to use floating point arithmetic.