Differences between revisions 60 and 70 (spanning 10 versions)
Revision 60 as of 2008-12-21 11:21:51
Size: 193
Editor: catv-89-134-159-5
Comment: 3.33333333333333
Revision 70 as of 2010-07-13 12:19:21
Size: 3683
Editor: GreyCat
Comment:
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
Nice page ;) But thinking again kitchen Keep up the good work!!! http://markseh.kilu.de/recipe627.html potatoes third, http://markseh.kilu.de/recipe18c.html kitchen, With respect admiration. <<Anchor(faq22)>>
== How can I calculate with floating point numbers instead of just integers? ==
[[BASH]] does not have built-in floating point [[ArithmeticExpression|arithmetic]]:

{{{
    $ echo $((10/3))
    3
}}}

Bash cannot do ''anything'' with floating point numbers, ''including'' compare them to each other(*). Instead, 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}}} (reversed polish calculator, lighter than bc):
{{{
    $ echo "3 k 10 3 / p" | dc
}}}

{{{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, 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`:

{{{
    # This would work with some versions, but not HP-UX 10.20.
    # The here string feature, inherited from rc->zsh->ksh93 was
    # introduced in bash 2.05b-alpha1
    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.

Newer versions of zsh and the KornShell have built-in floating point arithmetic, together with mathematical functions like {{{sin()}}} or {{{cos()}}} .

Caveat: 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.

(*)Actually, I lied. It can print them, using {{{printf}}} and one of the {{{%e}}} or {{{%f}}} or {{{%g}}} format strings. But that's all.

----
CategoryShell

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

BASH does not have built-in floating point arithmetic:

    $ echo $((10/3))
    3

Bash cannot do anything with floating point numbers, including compare them to each other(*). Instead, 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 (reversed polish calculator, lighter than bc):

    $ echo "3 k 10 3 / p" | dc

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, 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:

    # This would work with some versions, but not HP-UX 10.20.
    # The here string feature, inherited from rc->zsh->ksh93 was
    # introduced in bash 2.05b-alpha1
    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.

Newer versions of zsh and the KornShell have built-in floating point arithmetic, together with mathematical functions like sin() or cos() .

Caveat: 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.

(*)Actually, I lied. It can print them, using printf and one of the %e or %f or %g format strings. But that's all.


CategoryShell

BashFAQ/022 (last edited 2021-09-01 06:31:58 by geirha)