Операция заказа для максимизации двойной точности
Я работаю над некоторым инструментом, который вычисляет числа, которые могут приблизиться к 1e-25
в худших случаях и сравнивать их вместе, на Java. Я, очевидно, использую двойную точность.
Я прочитал в еще один ответ, который я не должен ожидать больше, чем 1e-15
до 1e-17
, и этот другой вопрос касается повышения точности при упорядочивании операций в "лучшем" порядке.
Какие операции с двойной точностью более склонны к снижению точности на этом пути? Должен ли я попытаться работать с номером как можно большим или малым? Делать деления сначала перед умножением?
Я бы предпочел не использовать классы BigDecimal
или эквивалент, так как код уже достаточно медленный;) (если только они не Конечно, скорость удара слишком велика).
Любая информация будет принята с благодарностью!
EDIT. Тот факт, что числа являются "маленькими" по абсолютной величине (1е-25), не имеет значения, так как двойной может спуститься до 1е-324. Но важно то, что, когда они очень похожи (оба в 1е-25), мне приходится сравнивать, скажем, 4.64563824048517606458e-21 - 4.64563824048517606472e-21 (разница 19 и 20 цифр). Когда вычисляет эти числа, разница настолько мала, что я могу ударить по "ошибке округления", где остаток заполняется случайными числами.
Возникает вопрос: "как упорядочить вычисления так, чтобы эта потеря точности была минимизирована?". Это может быть деление перед умножением или добавлением в первую очередь.
Ответы
Ответ 1
Благодаря @John за то, что вы указали очень полную статью о арифметике с плавающей запятой.
Оказывается, что, когда требуется точность, операции должны быть переупорядочены, а формулы адаптированы для предотвращения потери точности, как описано в Отмена: при сравнении чисел, которые очень близки друг к другу (это мой случай), может произойти "катастрофическое аннулирование", что приводит к огромной потере точности. Часто повторная запись формулы или операции переупорядочения в соответствии с вашими априорными знаниями значений операндов могут привести к достижению большей точности в исчислении.
Что я буду помнить из этой статьи:
- будьте осторожны при вычитании двух почти одинаковых величин
- попытайтесь повторно организовать операции, чтобы избежать катастрофической отмены
В последнем случае помните, что вычисление (x - y) * (x + y)
дает более точные результаты, чем x * x - y * y
.
Ответ 2
Если важно получить правильный ответ, вы должны использовать BigDecimal. Он медленнее, чем двойной, но в большинстве случаев он достаточно быстр. Я не могу придумать много случаев, когда вы делаете много вычислений с такими маленькими числами, где не имеет значения, правильный ответ - по крайней мере, с Java.
Если это приложение с высокой степенью производительности, я бы подумал об использовании другого языка.