next up previous 405
Next: Intrinsic Functions
Up: Arithmetic
Previous: Logical


Floating Point

The shell cannot perform non-integer arithmetic. Thus you need to employ some other utility. The standard UNIX bc arbitrary-precision calculator is one. You can also define an algebraic calculator with awk or gawk as shown below.

small

     alias acalc '       awk "BEGIN{ print \!* }" '

     set z = `acalc (sqrt(3.2)+exp(5.4))*4.1/5.2`
     set circle_area = `acalc atan2(0,-1)*${rad}*${rad}`
It is inadvisable to name the alias calc for reasons that will soon be evident. Note that in expressions you don't escape the multiplication sign and the expression is not in " quotes. The small set of about ten mathemetical functions available in awk, including arctangent shown above that evaluates $\pi$, limits what you can achieve. Another option is the KAPPA calc command. calc has most of the Fortran intrinsic functions available. For the remainder of this section, we shall just deal with calc.

The calc tool evaluates Fortran-like expressions, sending the result to standard output. So suppose that we wish to add two real values.

     set a = 5.4321
     set b = 1.2345
     set c = `calc $a+$b`
The variable c takes the value of adding variables a and b. Note the back quotes that cause calc to be executed.

This is fine if you know that the values will always be positive. However, calc will object if there are adjacent mathematical operators, such as +- as would happen if b were negative. So surround variables in parentheses, remembering that the ( ) are metacharacters. Click here for more details.

Let's redo the first example along with a few more to illustrate the recommended syntax. This time we'll specify the expression by parameter name rather than position.

     set a = 5.4321
     set b = -1.2345
     set c = `calc exp="($a)+($b)"`                     # c = 4.1976
     set d = `calc exp="'( $a - 0.5 * ($b) ) / 100 '"`  # d = 0.0481485
     set e = `calc exp="(($a)+($b))**3"`                # e = 296.2874
     set f = `calc exp="'($a + ($b)) ** 3'"`            # f = e
Don't be intimidated by the surfeit of quotes. The " " are needed because we want the dollar to retain its variable-substitution meaning. If the expression contains embedded spaces (usually for clarity) it should be enclosed in single quotes as shown in the assignment to variable f. So in general the recipe for using calc is

set variable = `calc exp="'expression'"`

Don't try to escape all the metacharacters individually because it can soon become very messy, error prone, and hard to follow.


The default precision is single precision. If you need more significant figures then append prec=_double to the calc command line. The special symbol pi has the value of $\pi$. So

     set arc = 0.541209
     set darc = `calc exp=$arc*180.0/pi prec=_double`
converts an angle 0.541209 radians (stored in arc) to degrees using double-precision arithmetic.

It is sometimes easier to assemble the expression in another variable. Here's another recipe which demonstrates this approach. Suppose that you want to find the average median value for a series of NDFs.

     # Estimates the median of each sky frame and subtracts it from that image

     # Enable KAPPA commands.  Initialise variables.
     kappa > /dev/null
     set first = 0
     set numndf = 0

     # Loop for all NDFs
     foreach file (*_fl.sdf)

     # Obtain the NDF's name.
        set file1 = $file:r

     # Assign the median value of the frame.  HISTAT computes the median,
     # and PARGET extracts it from HISTAT's MEDIAN output parameter.
     # Dispose of the HISTAT text output to the null file.
        histat $file1 \\ > /dev/null
        set median = `parget median histat`

     # Subtract the median from the input NDF.
        csub $file1 $median  $file1"_m" 

     # Count the number of NDFs.
        @ numndf = $numndf + 1

     # Form the string to sum the median values using CALC.  The shell
     # only permits integer arithmetic.  The expression is different
     # for the first file. 
        if ( $first == 0 ) then
           set expr = "( "$median
           set first = 1

     # Append a plus sign and the next median value.
        else
           set expr = `echo $expr" + "$median`
        endif

     end

     # Complete the expression for evaluating the average of the frame
     # medians.
     set expr = `echo $expr" ) / " $numndf`

     # Evaluate the expression and report the result.
     echo "Average median is "`calc $expr`
The script builds an expression to evaluate the average of the median values. So the first time it has to write the left parenthesis and first median value into string variable expr, but otherwise each new value is appended to the expression. Once all the medians are evaluated, the remainder of the expression, including division by the number of NDFs is appended. Finally, the expression is evaluated using calc. If you want to learn more about the set median = `parget median histat` command click here.

next up previous 405
Next: Intrinsic Functions
Up: Arithmetic
Previous: Logical

C-shell Cookbook
Starlink Cookbook 4
Malcolm J. Currie
2006 November 26
E-mail:ussc@star.rl.ac.uk

Copyright © 2009 Science and Technology Facilities Council