Reputation: 755
I have input file with with x1 , x2 and x values, I want to check if x is midpoint between x1 and x2. But the comparison is failing.
sample input file
x1=20.9280 x2=20.9600 x=20.9440
x1=20.9280 x2=20.9600 x=20.9440
x1=22.7840 x2=22.8160 x=22.8000
Awk command
awk -F'[ =]' '{ if(($2 + $4)/2 != ($6)) print ($2 + $4)/2, " ", $6;}' sample
OUTPUT
20.944 20.9440
20.944 20.9440
22.8 22.8000
Comparison is failing due to extra zeros after decimal points. Please help to fix it.
Upvotes: 1
Views: 1104
Reputation: 203985
As others have pointed out, if you are having a problem then it's probably that you're just tripping over the common floating point arithmetic issue but since all of your input values have the same precision you can just get rid of the .
s to treat the input numbers as integers and multiply by 2 instead of dividing by 2 just to keep it an integer comparison too:
$ awk -F'[ =]' '{o=$0; gsub(/\./,"")} ($6*2) == ($2+$4){$0=o; print ($2+$4)/2, $6}' file
20.944 20.9440
20.944 20.9440
22.8 22.8000
$ awk -F'[ =]' '{o=$0; gsub(/\./,"")} ($6*2) != ($2+$4){$0=o; print ($2+$4)/2, $6}' file
$
Upvotes: 0
Reputation: 785491
This is happening due to floating point comparison issue commonly found in all platforms.
You may use this awk
for floating point number comparison by converting number to a floating point with 4 decimal points:
awk -F'[ =]+' '{avg = sprintf("%.4f", ($2 + $4) / 2)} avg != $6 { print avg, $6 }' file
If you have gnu awk
then you can set precision to a lower number:
awk -M -v PREC=30 -F'[ =]+' '{avg = ($2 + $4) / 2; $6 += 0} avg != $6 { print avg, $6 }' file
Upvotes: 1
Reputation: 37424
Not really an anwser but do demonstrate. You are comparing floating point numbers, they are not equal. I replaced print
with printf
and modifiers with enough decimals (20, %.20f
):
$ awk -F'[ =]' '{
if(($2 + $4)/2 != ($6))
printf "%.20f %.20f\n", ($2 + $4)/2, $6
}' file
Ottput:
20.94400000000000261480 20.94399999999999906208
20.94400000000000261480 20.94399999999999906208
22.79999999999999715783 22.80000000000000071054
So use sprintf
and appropriate modifiers (see the printf
I used) to control the values.
Upvotes: 1