basel117
basel117

Reputation: 189

unsuccessful use of bc in float point math in shel

#!/bin/bash
    step=0.05
    short=0.05
    long=0.95
    for firstloop in {1..20}; do
        ratio=0.05
        for secondloop in {1..20} ; do
            echo $short $long $ratio >> file.txt
            time python3 main.py $short $long $ratio >> file.txt
            ratio= `echo $ratio + $step` | bc
        done
        short= `echo $short + $step`| bc
        long= `echo $long + $step`| bc

    done

when Iexecute the code this is what I get:

./script.sh: line 10: 0.05: command not found

real    0m25.329s
user    0m24.770s
sys 0m0.263s
./script.sh: line 10: 0.05: command not found

real    0m34.666s
user    0m32.319s
sys 0m0.623s
./script.sh: line 10: 0.05: command not found

real    0m31.425s
user    0m29.329s
sys 0m0.588s
./script.sh: line 10: 0.05: command not found

I have tried many variations so that I can increment the variables short, long and ratio with a float value. I know I can't deal with float points math in shell unless I use bc. I still haven't succeeded. what am I doing wrong?

After fixing the spaces errors and the format of bc as mentioned in the answer down below. I am left with this output:

real    0m0.871s
user    0m0.497s
sys 0m0.166s
++ echo '0 + 0.05'
++ bc
+ ratio=.05
+ for secondloop in '{1..20}'
+ echo 0 1 .05
+ python3 main.py 0 1 .05
Traceback (most recent call last):
  File "main.py", line 46, in <module>
    main()
  File "main.py", line 17, in main
    probability = [float(x) for x in sys.argv[:2]]
  File "main.py", line 17, in <listcomp>
    probability = [float(x) for x in sys.argv[:2]]
ValueError: could not convert string to float: 'main.py'

this is basically what I get repeatedly while the values of the 3 variable change.

Upvotes: 1

Views: 240

Answers (1)

Gordon Davisson
Gordon Davisson

Reputation: 125788

First, I'll make a style recommendation: use $( ) instead of backticks. They're mostly equivalent, except they're easier to read and have slightly cleaner syntax (using escapes inside backticks or nesting backticks are ... odd). Also, it's generally a good idea to put double-quotes around variable references (e.g. use python3 main.py "$short" "$long" "$ratio" instead of python3 main.py $short $long $ratio).

Now, the real problems: first, you can't put spaces around the = in an assignment, or it'll be parsed as something completely different. In general, spaces are critical delimiters in shell syntax, and you shouldn't either add or remove them when copying examples.

Compare these commands:

ratio=0.05
ratio= 0.05
ratio = 0.05

The first does what it looks like -- sets the variable ratio to "0.05". The second is equivalent to ratio='' 0.05 -- it tries to run "0.05" as a command, with the variable set to the empty string. This is what your script is doing, which is why you're getting the error "0.05: command not found". The third command tries to run "ratio" as a command, and pass it the arguments "=" and "0.05".

The second problem is that you have the pipe to bc outside the capture. Compare these commands:

ratio=$(echo "0.05 + 0.05" | bc)
ratio=$(echo "0.05 + 0.05") | bc

The first runs echo "0.05 + 0.05" | bc as a pipeline, and then captures the output and stores it in the variable ratio. This is what you want. The second sets ratio to "0.05 + 0.05" (the output of echo "0.05 + 0.05"), and then pipes the output of that (there isn't any) to bc. The output of bc (if there were any) would be printed to the Terminal rather than being captured.

In summary, you should replace every line like this:

ratio= `echo $ratio + $step` | bc

with something like this:

ratio=$(echo "$ratio + $step" | bc)

Upvotes: 2

Related Questions