Я пишу физический симулятор в C++, и меня беспокоит надежность. Я читал, что катастрофическая аннулирование может произойти в арифметике с плавающей запятой, когда вычисляется разность двух чисел почти равной величины. Мне пришло в голову, что это может произойти в симуляторе при вычислении точечного произведения двух почти ортогональных векторов. Однако ссылки, на которые я смотрел, обсуждают только решение проблемы, переписывая соответствующее уравнение (например, квадратичная формула может быть переписана для устранения проблемы) - но это не кажется применимым при вычислении точечного произведения? Наверное, мне было бы интересно узнать, является ли это, как правило, проблемой в физическом движке и как она адресована.
Является ли катастрофическая аннулирование проблемой при вычислении точечных продуктов векторов с плавающей запятой? И если да, то как это обычно решается?
Ответ 1
Один общий трюк состоит в том, чтобы сделать переменную аккумулятора типом с более высокой точностью, чем сами векторы.
В качестве альтернативы можно суммировать Кахан при суммировании терминов.
Другой подход заключается в том, чтобы использовать различные алгоритмы блокированных точечных продуктов вместо канонического алгоритма.
Разумеется, можно объединить оба вышеуказанных подхода.
Обратите внимание, что выше приведено общее поведение ошибок для точечных продуктов, а не только катастрофическое аннулирование.
Ответ 2
Вы говорите в комментарии, что вам нужно рассчитать x1 * x2 + y1 * y2, где все переменные являются поплавками. Поэтому, если вы выполняете вычисления с двойной точностью, вы не теряете никакой точности, потому что двойная точность имеет в два раза больше бит точности, чем float (при условии, что ваша цель использует IEEE-754).
В частности: пусть xx, yy
- действительные числа, представляемые float
переменными x, y
. Пусть xxyy
- их произведение, а xy
- результат умножения двойной точности x * y
. Тогда во всех случаях xxyy
- действительное число, представленное xy
.