0

I am comparing the floating point values in shell script based on this reference. Following is the script contents

num1=50.960
num2=6.65E+07
echo "${num1} < ${num2}" | bc

When I ran the script the output is '0'. But according to the comparison it should be '1'. I need inputs on why the comparison is not working as expected ?

Raja
  • 133

4 Answers4

2

The bc utility does not understand 6.65E+07 as the number you want it to be.

On OpenBSD, the E here is hexadecimal, so 6.65E is 6.664 (6.65 + 0.014), and then +07 will add 7 to that, yielding 13.664, and that is clearly less than 50.960. On GNU systems, 6.65E is 6.659 which is also not what you want.

Instead, you want num2 to be the string 6.65*10^7 or 66500000.

$ num1=50.960; num2='6.65*10^7'; printf '%s < %s\n' "$num1" "$num2" | bc
1
Kusalananda
  • 333,661
  • 2
    FWIW, GNU bc treats 6.65E as 6.659. If it treated 6.65E as a hex number, I'd expect it to yield 6.39794921875 (see printf '%.15g\n' 0x6.65E) – Stéphane Chazelas Mar 16 '21 at 11:15
  • @StéphaneChazelas Ah, so this is on OpenBSD. I should mention that. – Kusalananda Mar 16 '21 at 11:16
  • @StéphaneChazelas What I meant was that it seems to do an addition of 14 scaled to the position of the E in the number somehow. In any case, it's not doing what the user want it to. – Kusalananda Mar 16 '21 at 11:19
  • @Kusalananda, On stackoverflow, it's suggested to use "E" for scientific notation. Are those inputs wrong ? https://stackoverflow.com/a/31087503/8994194 – Raja Mar 16 '21 at 11:28
  • 1
    @Raja Yes, that is wrong. I don't know if that was correct advice at some point, but it's not correct today. – Kusalananda Mar 16 '21 at 11:33
0

If you want to use num2 as is you could use awk:

awk -v num1="$num1" -v num2="$num2" 'BEGIN{exit num1<=num2}'

This will compare the two numbers and exit 1 if num1 is less than num2 or exit 0 otherwise.

Note: this will exit 1 if num1 and num2 are equal which is the same behavior you would see from bc in that case, if you want it to exit 0 in that case you will need to use < instead of <=.

jesse_b
  • 37,005
0

One way is to use the dc utility by first converting the engineering notation to floating point.

num1=50.960
num2=6.65E+07

set -- "$num1" "$num2"

e2f() { case $1 in [eE]) :;; ) set -- "$1e0" esac set -- "${1//+/}" set -- "${1//-/ _}" set -- "${1//[eE]/ 10 }" echo "$1^" }

eCmp() { test "$(dc -e " 15k[1p]sa$(e2f "$1") $(e2f "$2")r>a")" = 1 }

and then...

if eCmp "$@" then echo "$1 > $2" else echo "$1 <= $2" fi

Output:

50.960 <= 6.65E+07
guest_7
  • 5,728
  • 1
  • 7
  • 13
0

Yes, bc could perform all kinds of math operations. But it doesn't understand floats. Modern shell's printf understand floats but can not do math.

Let's join them:

$ num1=50.960
$ num2=6.65E+07
$ printf '%f < %f\n' "$num1" "$num2" | bc -l
1