Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Floating point comparison with variable in bash [duplicate]

Tags:

I want to compare a floating point variable to an integer. I know this is not the best to do with bash, but my whole script is already written in bash. $number can be any integer. If it below or equal 50, I want output1, for all others I want an output with the other variable k. This is what I have so far:

number=43 test=$(echo "scale=2; $number/50" | bc -l) echo "$test" for k in {1..5} do     if ["$test" -le 1]     then echo "output"      elif ["$test" -gt $k]     then echo "output$k"     fi done 

If I try with test=0.43, the first loop does not even work. I think it has to do with an integer and a floating point comparison but cannot make it work.

Anything I am missing?

PS:this [0.43: command not found is what the terminal outputs.

like image 355
user1983400 Avatar asked Mar 05 '13 13:03

user1983400


People also ask

What is a better way to compare floating point values?

To compare two floating point values, we have to consider the precision in to the comparison. For example, if two numbers are 3.1428 and 3.1415, then they are same up to the precision 0.01, but after that, like 0.001 they are not same.

Why do we never use == to compare floating point numbers?

In the case of floating-point numbers, the relational operator (==) does not produce correct output, this is due to the internal precision errors in rounding up floating-point numbers. In the above example, we can see the inaccuracy in comparing two floating-point numbers using “==” operator.

How does Bash calculate floating points?

While you can't use floating point division in Bash you can use fixed point division. All that you need to do is multiply your integers by a power of 10 and then divide off the integer part and use a modulo operation to get the fractional part. Rounding as needed.


1 Answers

Bash can't handle floats. Pipe to bc instead:

if [ $(echo " $test > $k" | bc) -eq 1 ] 

The error you see though is because the test command (i.e. the [) needs spaces before and after

It is even better to use (( ... )) since you compare numbers like this:

if (( $(bc <<< "$test > $k") )) 

The part in the loop should look like this:

if (( $(bc <<< "$test <= 1") )) then     echo "output" elif (( $(bc <<< "$test > $k") )) then     echo "output$k" fi 

Relational expressions evaluate to 0, if the relation is false, and 1 if the relation is true [source]. Note however that is a behavior of GNU bc, and it is not POSIX compiant.

like image 101
user000001 Avatar answered Oct 26 '22 23:10

user000001