bc: prevent "divide by zero" runtime error on multiple operations

2.9k views Asked by At

I'm using bc to do a series of calculation.

I'm calling it though a bash script that first of all puts all the expressions to be calculated in a single variable, the passes them to bc to calculate the results.

The script is something like that:

#!/bin/bash
....

list=""

for frml in `cat $frmlList`
do
    value=`echo $frml`
    list="$list;$value"
done

echo "scale=3;$list"| bc

the frmlList variable contains a list of expressions that are the output of another program, for simplicity i don't mention every operation, but on its contents are done some sed operations before to assign it to the "value" variable.

In the end, the "list" variable contains a list of expressions separated by semicolon that bc understands.

Now what happens is that in my formula list, sometimes happens that there is a division by 0.

When it happens bc stops its computation giving a "Runtime Error: divide by zero".

I would bc to not end its work on that error, but to skip it and continue with the next formula evaluation.

Is possible to achieve something like that?

The same thing happens in a simpler situation:

echo "scale=2;1+1;1/0;2+2;" | bc

the output is

2
Runtime error (func=(main), adr=17): Divide by zero

I would like to have something like

2
Runtime error (func=(main), adr=17): Divide by zero
4

Thank you in advance :)

2

There are 2 answers

0
giocarmine On BEST ANSWER

Ok, in the end i found a workaround that does the trick quite well.

The idea is to parallelize the execution of bc using subshells, this way if an evaluation fails the other can be still done.

In my script i did something like this:

#!/bin/bash
i=0

for frml in `cat $frmlList`
do
    i=$((i+1))
    (echo "scale=3;$value"| bc -l extensions.bc > "file_$i.tmp") &

    if (( $i % 10 == 0 )); then
      wait;
    fi # Limit to 10 concurrent subshells.
done

#do something with the written files
1
Aaron Digulla On

I know no simple way to do this. If the expressions are independent, you can try to run them all in bc. If that fails, feed them to bc one by one, skipping the broken ones.

If expressions depend on each other, then you probably need something more powerful than bc. Or you can try to append expression after expression to an input file. If bc fails, remove the last one (maybe restore the file from a backup) and try with the next one.