3

I am currently learning the world of bash scripting. I am aware that bash by itself does not do arithmetic with floating integers. I have done some research and have found that there are tools that can help get the job done. I decided to use the bc calculator tool. The only issue is the syntax. I am able to get results but not in the desired way. How can I assign $N_RESULTS the value of the math operation?

//I get arithmetic error with this syntax
DECI=128.17333
let "N_RESULTS = ($DECI - 1) / 10 + 1" | bc -l
echo $N_RESULTS

_

//I get correct results if do something like this
DECI=128.17333
echo "($DECI - 1) / 10 + 1" | bc -l

1 Answer 1

2
N_RESULTS=$( echo "($DECI - 1) / 10 + 1" | bc -l )

What let does

Consider:

let "N_RESULTS = ($DECI - 1) / 10 + 1" | bc -l

This pipeline has two parts. The first is the shell's let command. Because of the | symbol, output from the let command is passed to stdin of the bc command. While 'let is capable of performing integer arithmetic and can assign values to variable, it does not produce any output. Hence, even if it ran correctly, it would pass nothing to bc.

Here is an example of a working let command:

$ let "result = (123 - 1) / 10 + 1"
$ echo $result
13

If, however, we were to supply a floating point argument, an error would result:

$ let "result = (123.0 - 1) / 10 + 1"
bash: let: result = (123.0 - 1) / 10 + 1: syntax error: invalid arithmetic operator (error token is ".0 - 1) / 10 + 1")

The let command, like the rest of the shell, only does integer arithmetic.

What bc does

bc does floating point arithmetic and can be used to assign and manipulate variables:

$ echo "result = (123.0123 - 1) / 10 + 1; print result" | bc -l
13.20123000000000000000

Note, however, that the above does not, by itself create any shell-usable variables. The definition of result expires when the bc finishes processing. In order to pass the value back to the shell, we need to do a shell variable assignment such as:

$ result=$(echo "(123.0123 - 1) / 10 + 1" | bc -l )
$ echo $result
13.20123000000000000000

The $(...) construct is called command substitution. It runs a command, in this case the echo and bc pipeline, and puts its stdout on the command line where it is assigned to the variable result.

As a side note, it usually considered best practices to use lower-case names for your shell variables. The system's shell variables are all upper-case and you don't want to accidentally overwrite one of them.

What is the bc equivalent for [[ $offset -lt $result ]]

The shell test commands, including [ and [[, produce a useful exit code that can be used in if, while, and other contexts, such as && and ||, where exit codes are used to determine program flow. bc does not emulate that behavior. It returns an exit code of 0 for any successful calculation. It returns non-zero exit codes if an error occurred. The examples below show how, with the help of grep, bc can be used to set useful exit codes.

In GNU bc, relational expressions evaluate to 1 for true and 0 for false. So, to test whether offset is less than result, we just check whether bc returns 0 or 1. Here, grep is used to examine the output from bc and set an appropriate return code that can be used in if, while, or other places where the shell would test for a return code. For example:

$ offset=1.25; result=1.33
$ echo "$offset < $result" | bc -l | grep -q 1 && echo yes || echo no
yes
$ offset=1.35
$ echo "$offset < $result" | bc -l | grep -q 1 && echo yes || echo no
no

Under non-GNU bc, the same thing can be done but a formal if statement is required:

echo "if ($offset < $result) print 1 else print 0 " | bc -l | grep -q 1 && echo yes || echo no
3
  • +1 This is a great explanation. One more thing. How would I be able to do comparison with a floating point number while [[ $OFFSET -lt $result ]] ; do ? Oct 5, 2014 at 4:15
  • @Code_Ed_Student See updated answer.
    – John1024
    Oct 5, 2014 at 5:52
  • I have another question based on similar topic: superuser.com/questions/821023/… Oct 5, 2014 at 6:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .