не работает сравнение с плавающей запятой awk - PullRequest
1 голос
/ 24 апреля 2020

У меня есть входной файл со значениями x1, x2 и x, я хочу проверить, является ли x средней точкой между x1 и x2. Но сравнение не удается.

образец входного файла

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

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

Сравнение не удается из-за дополнительные нули после десятичных знаков. Пожалуйста, помогите исправить это.

Ответы [ 3 ]

1 голос
/ 24 апреля 2020

Не совсем, но продемонстрируйте. Вы сравниваете числа с плавающей запятой, они не равны. Я заменил print на printf и модификаторы с достаточным количеством знаков после запятой (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

Так что используйте sprintf и соответствующие модификаторы (см. printf, который я использовал) для управления значениями.

1 голос
/ 24 апреля 2020

Это происходит из-за проблемы сравнения с плавающей запятой, обычно встречающейся на всех платформах.

Вы можете использовать эту awk для сравнения чисел с плавающей запятой путем преобразования числа в число с плавающей запятой с 4 десятичными точками:

awk -F'[ =]+' '{avg = sprintf("%.4f", ($2 + $4) / 2)} avg != $6 { print avg, $6 }' file

Если у вас gnu awk, вы можете установить точность на меньшее число:

awk -M -v PREC=30 -F'[ =]+' '{avg = ($2 + $4) / 2; $6 += 0} avg != $6 { print avg, $6 }' file
0 голосов
/ 24 апреля 2020

Как уже отмечали другие, если у вас возникла проблема, то, вероятно, вы просто отключаетесь от общей арифметической проблемы c, но поскольку все ваши входные значения имеют одинаковую точность, вы можете просто избавиться от них. из . s для обработки входных чисел как целых чисел и умножения на 2 вместо деления на 2, чтобы также сохранить целочисленное сравнение:

$ 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
$
...