Daily Linux / Unix

 
 
 

User Tools

Site Tools


floating_point_calculation

Floating Point Calculation

This is an example represent how to compute Floating point in bash.

Using in Script for Comparision

To use bc in our bash scripts we'll package it up into a couple of functions:

    float_eval EXPRESSION
and
    float_cond CONDITIONAL-EXPRESSION
Both functions expect a single floating point expression, float_eval writes the result of the expression evaluation to standard out, float_cond assumes the expression is a conditional expression and sets the return/status code to zero if the expression is true and one if it's false.

Usage is quite simple:

  float_eval '12.0 / 3.0'
  if float_cond '10.0 > 9.0'; then
    echo 'As expected, 10.0 is greater than 9.0'
  fi
  a=12.0
  b=3.0
  c=$(float_eval "$a / $b")
The code for the functions follows:

#!/bin/bash
#
# Floating point number functions.
 
#####################################################################
# Default scale used by float functions.
 
float_scale=2
 
 
#####################################################################
# Evaluate a floating point number expression.
 
function float_eval()
{
    local stat=0
    local result=0.0
    if [[ $# -gt 0 ]]; then
        result=$(echo "scale=$float_scale; $*" | bc -q 2>/dev/null)
        stat=$?
        if [[ $stat -eq 0  &&  -z "$result" ]]; then stat=1; fi
    fi
    echo $result
    return $stat
}
 
 
#####################################################################
# Evaluate a floating point number conditional expression.
 
function float_cond()
{
    local cond=0
    if [[ $# -gt 0 ]]; then
        cond=$(echo "$*" | bc -q 2>/dev/null)
        if [[ -z "$cond" ]]; then cond=0; fi
        if [[ "$cond" != 0  &&  "$cond" != 1 ]]; then cond=0; fi
    fi
    local stat=$((cond == 0))
    return $stat
}
 
 
# Test code if invoked directly.
if [[ $(basename $0 .sh) == 'float' ]]; then
    # Use command line arguments if there are any.
    if [[ $# -gt 0 ]]; then
        echo $(float_eval $*)
    else
        # Turn off pathname expansion so * doesn't get expanded
        set -f
        e="12.5 / 3.2"
        echo $e is $(float_eval "$e")
        e="100.4 / 4.2 + 3.2 * 6.5"
        echo $e is $(float_eval "$e")
        if float_cond '10.0 > 9.3'; then
            echo "10.0 is greater than 9.3"
        fi
        if float_cond '10.0 < 9.3'; then
            echo "Oops"
        else
            echo "10.0 is not less than 9.3"
        fi
        a=12.0
        b=3.0
        c=$(float_eval "$a / $b")
        echo "$a / $b" is $c
        set +f
    fi
fi
 
# vim: tabstop=4: shiftwidth=4: noexpandtab:
# kate: tab-width 4; indent-width 4; replace-tabs false;
The work of the functions is done by feeding the arguments to bc:

   result=$(echo "scale=$float_scale; $*" | bc -q 2>/dev/null)
By default bc outputs its result with no digits to the right of the decimal point and without a decimal point. To change this you have to change one of bc's builtin variables: scale. This is where the “language” features of bc are relevant, in bc as in C statements are separated by semi-colons. We set bc's scale variable by preceding the expression that we pass to bc with scale=$float_scale;. This sets the scale in bc to the value of the bash global variable float_scale, which is by default set to two (near the top of the script).

The main gotcha here has to do with the fact that “*”, ”<”, and ”>” have other meanings in bash. You can eliminate the problem of ”<” and ”>” by quoting your expressions, but this only works with “*” if you use single quotes and that would mean you couldn't include bash variables in the expression. The other option is to bracket your code with ”set -f” and ”set +f” to turn off pathname/wildcard expansion.

If you save the script as float.sh and run it directly it will execute the test code at the bottom:

  $ sh float.sh
  12.5 / 3.2 is 3.90
  100.4 / 4.2 + 3.2 * 6.5 is 44.70
  10.0 is greater than 9.3
  10.0 is not less than 9.3
  12.0 / 3.0 is 4.00
The one unaswered question you may have is: “and why would I want to do this?” Next time around I'll show you one place you can put this to real world use.

Ref : Linux Journal

Doing Calculation

Details

If you are like me and you like to use the bash shell as much as possible, you have probably run into the situation where you wanted to have a calculator built into your bash shell. So with a 2 line script and an edit to your .bashrc file, your bash shell can become a useful basic calculator. No more firing up kcalc to do simple math. With the program bc and a very small bash script, you can now get those decimal places to show up.

The two line script.

#!/bin/bash
echo "scale=4; $1" | bc ;exit
Now save the script as bashcalc.sh

Now, you can do a couple of things at this point.

METHOD #1 If you're like me, you have a /home/crouse/Scripts directory (ok, so yours probably doesn't say crouse lol) and you put most of your scripts in there. The benefit of this is that it doesn't require any special privledges to accomplish.

mv bashcalc.sh /home/$USER/Scripts/bashcalc.sh
chmod a+x /home/$USER/Scripts/bashcalc.sh
Now that the script is in your script directory, you need an alias in the .bashrc file in order to make it work. Here is the alias in my .bashrc file for example:

alias calc='sh /home/crouse/scripts/bashcalc.sh'

METHOD #2 Alternatively, you can put the script into /usr/bin and there is no need to edit the .bashrc file as /usr/bin is in your bash shell's path. You at least need the ability to sudo or install as root to accomplish this method.

sudo cp bashcalc.sh /usr/bin/calc
sudo chmod 755 /usr/bin/calc
Once all of this text editing, moving, and assorted stuff is done, you can use calc and do floating point math with your bash shell!

Examples:

[crouse@localhost ~]$ calc 2.55*2.6666
6.7998
[crouse@localhost ~]$ calc 25.55/3.6666666
6.9681
[crouse@localhost ~]$ calc 25.2222+6.33333
31.55553
[crouse@localhost ~]$ calc 99-1.333333333
97.666666667
Notice that the division is only carried out to 4 places past the decimal point? That's a limitation of the bc command. You can override the 4 places to whatever you prefer by simply changing the line:

echo "scale=4; $1" | bc ;exit
The “scale=4” is what controls the amount of decimal places the division will calculate too. Just change the 4 to whatever length you prefer. Now you can do simple floating point math with just your bash shell.

Here is an adaptation of the first script that allows you to keep inputing calculations (kind of like a calculator) without having to restart the script every time:

FILE DOWNLOAD: http://www.bashscripts.org/downloads/Scripts/crouse/calc.sh

You can use the function above and extend it to create a sort of bash adding machine. It's a calculator that constantly runs in a bash shell.

You can edit the script to suit your needs, but it basically allows you to key in your problems, gives the results and waits for another problem to be input.

The default scale for division is to go 4 decimal places, this can be adjusted in the script to whatever length you wish to use. This was because I sometimes needed to enter in alot of individual calculations and was tired of typing the word calc :)

This could be extended even further and store individual calculations if you wanted it to, but that's beyond the scope of this article at the moment.

#!/bin/bash
 
#######################################################
#     Bash CALCulator 2
#######################################################
#
#
#    FILE: bashcalc2.sh
# VERSION: 1.1
#    DATE: 06-19-2006
#
#  AUTHOR: Crouse - Please visit bashscripts.org and usalug.org
#
#
########################################################
 
header ()
{
clear; echo "Bash Calculator - Enter a calculation and hit enter";
echo "---------------------------------------------------";
}
 
calc ()
{
header
while true
do read -p "" bashcalc;
       if [ "$bashcalc" = "quit" ]
         then
           exit
       fi
 
       if [ "$bashcalc" = "clear" ]
        then
          calc
       fi
 
       if [ "$bashcalc" = "help" ]
        then
          clear
          echo "Options include:"
          echo " help - This help file"
          echo " clear - Clears the screen"
          echo " quit - Quits the program"
          echo " "
          read -p  "Hit any key to continue" temp;
          calc
       fi
 
  echo "scale=4; ${bashcalc}" | bc ;
  echo "---------------------";
done
}
 
# Program run starts here
calc
 
exit 0

Ref. Novell Cool Solutions

floating_point_calculation.txt · Last modified: 2012/01/27 16:35 by k2patel