Компьютер, в отличие от "чистой" математики, оперирует не правильными числами, но их приближениями, точность которых технически ограничена. В абсолютном большинстве случаев погрешность ничтожна.
В этом постике - два случая из одной и той же строчки кода, когда она оказалась принципиальной.
Наверное, эту строчку следует использовать в целях карательной педагогики.
Случай первый. От перемены мест слагаемых сумма меняется.
Дано:
Есть массив oxmass_sum, каждый элемент
которого определяется по формуле, приведённой на картинке: oxmass_sum(i)
= oxmass_sum(i) + tmass*foxide(i) - mass_oxide_new(i).
Источник проблемы и к чему это приводит:
Значения массива oxmass_sum(:) могут быть порядка единицы и её десятых долей. С другой стороны, количество знаков tmass*foxide(i) превышает точность вычислений. Поэтому при вычислении при прибавлении к oxmass_sum(i) величины tmass*foxide(i) и выполнении дальнейших операций величина отбрасывается.
Решение:
Переставить oxmass_sum(i) в конец суммы:
oxmass_sum(i) = tmass*foxide(i) - mass_oxide_new(i) + oxmass_sum(i)
Комментарий:
Об этом меня предупреждали книжки 60-х годов. Однако их рекомендация была в суммах упорядочивать числа по возрастанию - и в данном случае она таки не срабатывает. Складывать надо после приведения к единому порядку величины.
Подход к пределу точности явно следует из
спецификации типа данных REAL*8.
PS: да, я глупый, порядок столбцов в третьей таблице
tmass, foxide(:), mass_oxide_new(:), oxmass_sum(:)_old, oxmass_sum(:)_new
Случай второй. Разница в адцатом знаке.
Дано:
Есть массив oxmass_sum, каждый элемент которого определяется по формуле, приведённой на картинке: oxmass_sum(i) = tmass*foxide(i) - mass_oxide_new(i) + oxmass_sum(i).
Источник проблемы:
Для расчёта массива mass_oxide_new(i) есть два массива cox(:) и cc(:), причём cc(:) - это изначальные значения, а cox(:) - те же, но полученные из другого источника (при этом они должны быть равны, т.к. считаются из одних и тех же констант, только по разным формулам). Как можно увидеть в строке вывода, представление чисел несколько отличается - хотя с точностью до энного знака числа полностью идентичны.
К чему это приводит:
При перемножении этих одних и тех же с машинной точностью (VARIANT 1) на скриншоте на константу tmass полученное третье значение массива cox отличается на 0.5 от cc(3)*tmass и foxide(3)*tmass. Как результат, массив с разностями получается ненулевой.
Несмотря на то, что полученная разность на много порядков меньше исходных величин, в дальнейшем расчёте она принципиальна: там уже идёт игра в малые числа.
Решение:
Физически приравнивать числа, если их разность меньше определённого предела. Массив получается нулевой.
Комментарий:
В принципе, просто иной поворот старого правила, что сравнивать два числа с плавающей точкой (if a == b then ...) некорректно и неправильно. Однако здесь домножение на Очень Большое Число tmass привело к тому, что исчезающая разность стала вполне расчётной величиной.
PS: а меня шеф похвалил! "It's great that you are finding some subtle bugs." уруру