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

BASH's builtin arithmetic uses integers only:

$ printf '%s\n' "$((10 / 3))" 3

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

$ printf 'scale=3; 10/3\n' | 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`):

$ printf '3 k 10 3 / p\n' | 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 non-integer numbers (less-than or greater-than), and you have GNU `bc`, you can do this:

# Bash and GNU bc if (( $(bc <<<'1.4 < 2.5') )); then printf '1.4 is less than 2.5.\n' 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 $(printf '%s - %s\n' 1.4 2.5 | bc) in -*) printf '1.4 is less than 2.5\n' ;; 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, zsh and yash have support for non-integers in shell arithmetic. zsh (in the `zsh/mathfunc` module) and ksh93 additionally have support for some 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 or zsh:

# ksh93/zsh/yash $ LC_NUMERIC=C; printf '%s\n' "$((3.00000000000/7))" 0.428571428571428571

(ksh93 and yash are sensitive to locale. In ksh93, a dotted decimal used in locales where the decimal separator character is not *dot* will fail, like in German, Spanish, French locales... In yash, the locale's decimal radix is only honoured in the result of arithmetic expansions.).

Comparing two non-integer 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 non-integer numeric results due to rounding/truncation and other issues. If you wish to determine whether two non-integer 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.

$ ksh93 -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 non-integer 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 printf 'a and b are roughly the same\n' fi

Many problems that look like non-integer 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 printf '16:9.\n' elif (( (x * 3 - y * 4) == 0 )) ; then printf '4:3.\n' else printf 'Neither 16:9 nor 4:3.\n' fi

A more elaborate test could tell if the ratio is closest to 4:3 or 16:9 without using non-integer arithmetic. Note that this very simple example that apparently involves non-integer 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 non-integer arithmetic.