Почему существует разница между этими двумя командами суммирования?

Почему существует разница между этими двумя командами суммирования?

У меня есть сценарий.

где я вычисляю сумму определенного столбца, используя две команды ниже

может ли кто-нибудь подробно объяснить мне, что на самом деле выполняет эта команда?

Первая команда [при использовании для вычисления суммы определенного столбца]

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чтобы получить лучшие результаты.

Основная проблема объясняется на этом сайте:
Что каждый программист должен знать об арифметике с плавающей точкой

Связанный контент