
у меня есть сценарий
У меня возникла проблема, потому что сумма UNIX по шкале от 8 до 9 выдает неправильную сумму. Как это исправить?
моя команда использовала
awk -F '"?\\|"?' '{T+=$(2)} END {printf "%.2f\n",T}' demofile.txt
Это ссылка на предыдущий вопрос, опубликованный Почему существует разница между этими двумя командами суммирования?
Есть ли лучший способ справиться с этим, чтобы я мог получить точную сумму?
с помощью awk или bc или dc
Демонстрационные данные
1|"12.8"|demo1
2|"13.5678341234567"|demo1
3|"14.578"|demo1
4|"15.58"|demo1
5|"16.56784"|demo1
6|"17.578"|demo1
7|"18.678"|demo1
8|"19.568890123"|demo1
9|"20.588792"|demo1
решение1
Вы не указываете размер файла (т. е. сколько строк вы добавляете). Загрузка потребовала 18,3 МБ, прежде чем сайт появился как «Опасный» и «Предупреждение о мошенничестве». Если средняя длина строки составляет 18, это миллион добавляемых чисел с плавающей точкой, и мы не знаем диапазон значений. Общая сумма, которую вы указываете в вопросе, составляет 13,2 цифры, поэтому среднее значение на строку составляет около 7 цифр с неизвестной изменчивостью.
Если вы продолжаете добавлять значения вроде 27,865326635297 к промежуточной сумме, которая приближается к 13 целым цифрам, то только часть 27,87 (округленная) попадет в общую сумму, потому что .00532... находится за пределами диапазона результата в 15 или 16 цифр. Иногда эти ошибки отменяются, иногда нет: арифметика Монте-Карло.
Проверьте вывод awk --version. Если там упоминаются MPFR и MP, ваш awk скомпилирован с расширенной точностью математики. Просто добавьте -M 113 к вашей команде awk. Это длина мантиссы, которая дает вам учетверенную точность вещественной арифметики — точность 33 знака.
www.gnu.org/software/gawk/manual/gawk.html#Arbitrary-Precision-Arithmetic
решение2
Это метод, основанный наОкруг Колумбиякоманда (предполагая, что в ней скомпилирована адекватная точность). Она одевает второй столбец с помощью команд dc и работает с точностью 60 цифр (200 бит).
Это работает на 10 строках данных, предоставленных ранее, плюс пара экстремальных значений. Он показывает промежуточные суммы: чтобы удалить их, удалите 'p' прямо перед \n, где awk выдает $2.
Paul--) cat awkToDc
#! /bin/bash
function Data { cat <<'EOF'
1|"12.8"|demo1
2|"13.5678341234567"|demo1
3|"14.578"|demo1
4|"15.58"|demo1
5|"16.56784"|demo1
6|"17.578"|demo1
7|"18.678"|demo1
8|"19.568890123"|demo1
9|"20.588792"|demo1
10|"55555555555555555555000000000000"|demo1
11|"20.588792"|demo1
12|"0.000000000000000000077777777777"|demo1
EOF
}
function dataDC {
AWK='
BEGIN { FS = "\042"; printf ("60 k 0\n"); }
{ printf ("%s + p\n", $2); }
END { printf ("p q\n"); }
'
awk "${AWK}"
}
Разъяснение по переданным командам постоянного тока (которые имеют обратную польскую запись):
«60 k» устанавливает арифметическую точность, а «0» инициализирует итог.
«+» добавляет значение из $2 к итогу. «p» выводит промежуточный итог для иллюстрации.
«p q» выводит окончательный итог и завершает работу.
Data | dataDC | dc
Paul--) ./awkToDc
12.8
26.3678341234567
40.9458341234567
56.5258341234567
73.0936741234567
90.6716741234567
109.3496741234567
128.9185642464567
149.5073562464567
55555555555555555555000000000149.5073562464567
55555555555555555555000000000170.0961482464567
55555555555555555555000000000170.096148246456700000077777777777
55555555555555555555000000000170.096148246456700000077777777777
Paul--)
Теперь у вас есть четыре протестированных метода (на вашем тестовом файле из 722277 строк) с оценками точности.
При использовании gawk с точностью 200 бит и dc с точностью 60 цифр оба дают один и тот же итог из 33 цифр, который, как я подозреваю, является точным.
25396577843.7560139069641121618832
Использование gawk в стандартной точности IEEE (должно быть 15 или 16 цифр) согласуется только с первыми 12 из этих цифр. Я предполагаю, что миллион добавлений подорвут точность, поскольку показатели степени станут более разрозненными.
25396577843.7769622802734375
Я также нашел алгоритм рекурсивного сложения в стандартном awk. Он изначально складывает значения в соответствии с последними 5 цифрами NR, чтобы получить 100 000 промежуточных итогов. Затем он суммирует их, уменьшая количество цифр до 4, 3, 2, 1 и, наконец, одного итога. Таким образом, каждое число получает только 60 сложений. Этот результат согласуется с первыми 16 цифрами высокоточных чисел, что настолько хорошо, насколько можно было ожидать.
25396577843.756011962890625
решение3
Проверитьсуммирование Кахана, он пытается отслеживать ошибку округления и компенсирует ее. Обязательно для таких огромных сумм.
решение4
С cvstool
и bc
:
$ csvtool -t '|' col 2 A | paste -sd + - | bc
149.5073562464567