0

So want to turn this function, whose output is a number. The number is curled through some json file thats irrelevant.

#error input 1
if (($(masterfunc) >= 1)); then
#I've also tried
#error input 2
if (($(masterfunc | bc -l) >= 1)); then

I get these this error, which I'm assuming is because its outputing it as a letter or command and not as a number.

#error output 1
((: 1.00048333447157914468 >= 1: syntax error: invalid arithmetic 
operator (error token is ".00048333447157914468 >= 1")
#error output 2
((: .99989817794934530799 >= 1: syntax error: operand expected (error 
token is ".99989817794934530799 >= 1")

I'm assuming this is some floating point arithmetic problem, but then it should of been solved through bc?

I'm new to bash so if the problem is some unrelated syntax error I apologize.

  • `((...))` simply doesn't support floating point. You can't use `bc` *inside* the parentheses as that still leaves `((...))` with floating point numbers. You need to do all of the math with `bc` and ditch `((...))`. – John Kugelman May 01 '18 at 02:13
  • Look up, i did use bc. – Caucasian Malaysian May 01 '18 at 02:24
  • I've looked at the floating point division in bash, no relevant info that i didn't know. – Caucasian Malaysian May 01 '18 at 02:26
  • 1
    @CaucasianMalaysian You used `bc`, but not in a relevant way. When you just pipe the number to `bc`, it looks at it, says "yep, that's a number" to itself, and then prints it *still as a real number*. Bash then tries to compare that with 1, but it's still a real number, so it fails. You need to have `bc` do the actual comparison, so all bash needs to deal with is a simple yes/no (or 1/0). – Gordon Davisson May 01 '18 at 02:38
  • So bc does the -ge part, what do you put in substitution for asking the if function to do a simple yes/no? Do you make it repeat the same comparison you're pipelining into bc? – Caucasian Malaysian May 01 '18 at 03:14

2 Answers2

2

This is actually rather complicated. The shell doesn't understand real numbers at all, so you have to get something else (like bc) to do the comparison and output something simpler that bash can understand. The simplest way I see to do this is:

if [ $(echo "$(masterfunc) >= 1" | bc) -eq 1 ]; then

Explanation, step by step:

  • echo "$(masterfunc) >= 1" runs the masterfunc function, adds ">= 1" to its output, and sends the result (something like "1.00048333447157914468 >= 1") to standard output.

  • echo "$(masterfunc) >= 1" | bc runs the above and pipes it to bc, which will do the comparison and print "1" if the masterfunc output is greater than or equal to 1, "0" if it's less. Note: you can try running this by hand and see how it works.

    This "1"/"0" output is more along the lines of what bash can understand, but we still need to actually tell bash what to make of it.

  • [ $(echo "$(masterfunc) >= 1" | bc) -eq 1 ] runs the above, captures its output with $( ), and embeds that in a test expression. Basically, depending on the output from bc, this is equivalent to either [ 1 -eq 1 ] or [ 0 -eq 1 ].

Gordon Davisson
  • 118,432
  • 16
  • 123
  • 151
  • There you go. I was going to use `$?` resulting from `echo "$(masterfunc) >= 1" | bc`, but throwing it all in `test` works too. – David C. Rankin May 01 '18 at 06:03
0

Use this:

if (( $(printf '%s >= 1\n' "$(masterfunc)" | bc -l) )); then ...
gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104