Floating point math operations in bash


When writing scripts in bash, sometimes we need to work with basic math functions. Like the trigonometric functions, square root, cube root, logarithms. Bash does not support floating point operations. This is where the problem is encountered, and we cannot write a math function of our own. There must be a way to do this, and yes. Bash supports redirections so we can feed the floating point computations and the math functions into some other program’s input who understands it. The program which can be used is the bc, which is an arbitrary precision calculator language. bc can do floating point operations, and also can do basic math functions. With bash and bc we can do the above. Continue reading to know how.

Check

Before doing anything first check if bc is installed in your system.To check if bc is installed execute the following:

rpm -q bc

If it says package bc is not installed then you need to install it. To install bc just execute the following in yum.

yum -y install bc

What’s the stuff

The main stuff is to simply write a string with echo and pipe it into the input of bc, and get the answer.

If we want to add two floating point numbers say 2.5 and 3.75, then simply the string “2.5+3.75″ should be feed into the input of bc and you are done. Check out the example below:

echo "2.5+3.75" | bc
6.25

Above the first line shows the input to bash, and the second line is the output.

As now you have understood the basic trick, that is so simply feed in any arithmetic expression into a program’s input, who understands it, to get the answer from it, i will present some more examples.

Examples

Now lets say you want to get a square root of a number (floating point), say 641 . The function of bc which performs square root is sqrt. And as we are performing a math function we need to tell bc to turn on its standard math library. This can be done just by including the -l switch to bc. So the command will be as below:

echo "sqrt(641)" | bc -l
25.31797780234432546177

Till now you should have guessed that we can also use the shell variables in the echo with double quotes to enable variable value. For example check the command sequence below:

x=215
echo "sqrt($x)" | bc -l

And yes now the command performs the square root of the variable “x” , which can be assigned whatever.

The below nano shell script performs floating point addition operation using bc.

	
#!/bin/bash
echo "Enter a floating point number: "
read a

echo "Enter another floating point number: "
read b

echo "Addition: "
echo "$a+$b" | bc

Integer powers of a floating point could be calculated with the “^” operator. Below “a” is a floating point and “b” is integer.

echo "$a^$b" | bc -l

So it is simple. Now some trigonometric functions. In bc the s is the sine function, c is the cos function, and the a is the arctangent function (atan). And as normal the angles are to be passed as radians, but we can always do a degree to radian conversion. So we have the basic two. The below shell script demonstrates the calculation of different trigonometric vales.

#!/bin/bash
echo "Enter angle in degree: "
read deg

# Note: Pi calculation
# tan(pi/4) = 1
# atan(1) = pi/4 and
# pi = 4*atan(1)

pi=`echo "4*a(1)" | bc -l`
rad=`echo "$deg*($pi/180)" | bc -l`

echo "$deg Degree = $rad Radian"

echo "Sin($deg): "
echo "s($rad)" | bc -l

echo "Cos($deg): "
echo "c($rad)" | bc -l

echo "Tan($deg): "
echo "s($rad)/c($rad)" | bc -l

The natural logarithmic function in bc is l. So to calculate natural logarithm and ten base logarithm we would do the following:

#!/bin/bash
echo "Enter value: "
read x

echo "Natural Log: ln($x) :"
echo "l($x)" | bc -l

echo "Ten Base Log: log($x) :"
echo "l($x)/l(10)" | bc -l

And similarly the exponential function could be implemented by calling the e function in bc.

You can adjust the precision of the value which the math functions calculate be assigning the decimal point accuracy in the scale variable within bc. For an example if you want square root of a number up to 2 decimal places, you should do as below, where “x” is the variable.

echo "scale=2;sqrt($x)" | bc -l

Note that it simply truncates the decimal places, so the scaled value is not the approximation but only truncated. For example 6.74536878161602073277 in 2 decimal places would be simple truncated to 6.74, and not 6.75

More

And now you can write a function in bc syntax and also make it use. As presented below, a factorial function:

#!/bin/bash

echo "Enter an integer: "
read n

# Below we define the factorial function in bc syntax
fact="define f (x) {
i=x
fact=1
while (i > 1) {
fact=fact*i
i=i-1
}
return fact
}"

# Below we pass the function defined above, and call it with n as a parameter and pipe it to bc
factorial=`echo "$fact;f($n)" | bc -l`

echo "$n! = $factorial"

Clearly any other functions written in bc syntax could be used

Resources

Check out more functions and operators and all the details of bc by visiting the site here: http://www.gnu.org/software/bc/manual/html_mono/bc.html , and also check the man page and info pages by executing:

man bc
info bc
About these ads

About phoxis

Homo-sapiens
This entry was posted in Computer Science, Linux / Unix Shell and tagged , , . Bookmark the permalink.

11 Responses to Floating point math operations in bash

  1. h446log says:

    Here’s a small tweak…
    If you use ksh, you can use shell co-processes instead of spawning ‘bc -l’ multiple times.
    —————————————————-
    #!/bin/ksh

    if [ $# -lt 1 ]; then
    echo -n “Enter angle in degree: ”
    read deg
    else
    deg=$1
    fi

    bc -l |&

    print -p “4*a(1)”
    read -p pi
    echo pi = $pi

    print -p “$deg*($pi/180)”
    read -p rad
    echo “$deg Degree = $rad Radian”

    print -p “s($rad)”
    read -p sin_degrees
    echo “Sin($deg): $sin_degrees”

    print -p “c($rad)”
    read -p cos_degrees
    echo “Cos($deg): $cos_degrees”

    print -p “s($rad)/c($rad)”
    read -p tan_degrees
    echo “Tan($deg): $tan_degrees”

    • phoxis says:

      Its even great with ksh then, no need to spawn multi processes each line. This could be done in bash by assigning the whole bc syntax into a shell variable and then pass the whole var into bc’s input. Just as described in the last example of the post.
      @h446log: Thanks for the great comment.

  2. Pingback: fractions in linux

  3. Pingback: [Praktikum SO] Referensi « Blog Iseng – Iseng Aja….. :)

  4. Peter Steier says:

    bc is not relly useful; no numbers with expnents (e.g. 1.22e9), and, (notoriously)
    echo “1/2″ | bc
    gives 0, which is simply wrong, if one ever attended school.
    I suggest to use
    echo “” | awk “{ print 1/2}”
    which gives 0.5, and supports the complete mathematical standard library.

  5. reberetta says:

    Thanks, your article was very helpful! :)

  6. reberetta says:

    Thanks, your article was very helpful!

  7. Carlord says:

    some how bc made the use of bash variables more complex, thought that is more helpfull to use awk than even when is less precise, the expansion of variables is possible and the line is less long and more readable when you don’t have the hardcoded values at the time you write an script

    • phoxis says:

      Other programs capable of floating point operations are fine as well. In case of bc, yes, constructing the script from bash variables seems a bit tricky and may be I would like to go with bc scripts. Although in actual application I use perl for scripting and for scientific computation octave and R. awk is not my game :D , may be you can post a sample awk script for similar floating point operations which can be used inside bash.

      Thanks for visiting!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s