У меня есть сценарий.
где я вычисляю сумму определенного столбца, используя две команды ниже
может ли кто-нибудь подробно объяснить мне, что на самом деле выполняет эта команда?
Первая команда [при использовании для вычисления суммы определенного столбца]
awk -F '"?\\|"?' '{T+=$(2)*1000} END {printf "%.2f\n",T/1000}' demofile.txt
Вторая команда [при использовании для вычисления суммы определенного столбца]
awk -F '"?\\|"?' '{T+=$(2)} END {printf "%.2f\n",T}' demofile.txt
когда сумма, рассчитанная с использованием обеих команд, различается. почему это так?
Это вывод: Это файл, используемый для расчета [загрузите и протестируйте] (ссылка удалена модератором, возможно, из-за проблем безопасности)
решение1
Разница в том, чтоgawk
руководствосостояния:
Двоичные представления с плавающей точкой и арифметика неточны. Простые значения, такие как ,
0.1
не могут быть точно представлены с использованием двоичных чисел с плавающей точкой, а ограниченная точность чисел с плавающей точкой означает, что небольшие изменения в порядке операций или точности промежуточного хранения могут изменить результат. Хуже того, при использовании арифметики с плавающей точкой произвольной точности вы можете задать точность до начала вычисления, но тогда вы не сможете быть уверены в количестве значимых десятичных знаков в конечном результате.
gawk
это GNU awk
. Он поддерживает-M
:
-M --bignum
Выбрать арифметику произвольной точности для чисел. Эта опция не имеет эффекта, если
gawk
не скомпилирована для использования библиотек GNU MPFR и MP.
Ваш awk
может быть эквивалентен или нет gawk
. В моем Debian 9 каждая из следующих двух команд выдает 25396577843.76
:
LC_NUMERIC=C gawk -M -v PREC=60 -F '"?\\|"?' '{T+=$(2)*1000} END {printf "%.2f\n",T/1000}' demofile.txt
LC_NUMERIC=C gawk -M -v PREC=60 -F '"?\\|"?' '{T+=$(2)} END {printf "%.2f\n",T}' demofile.txt
Хотя с printf "%.4f\n",T
я все еще вижу разницу. Увеличьте, PREC
чтобы получить лучшие результаты.
Основная проблема объясняется на этом сайте:
Что каждый программист должен знать об арифметике с плавающей точкой