Является ли катастрофическая аннулирование проблемой при вычислении точечных продуктов векторов с плавающей запятой? И если да, то как это обычно решается?

Я пишу физический симулятор в C++, и меня беспокоит надежность. Я читал, что катастрофическая аннулирование может произойти в арифметике с плавающей запятой, когда вычисляется разность двух чисел почти равной величины. Мне пришло в голову, что это может произойти в симуляторе при вычислении точечного произведения двух почти ортогональных векторов. Однако ссылки, на которые я смотрел, обсуждают только решение проблемы, переписывая соответствующее уравнение (например, квадратичная формула может быть переписана для устранения проблемы) - но это не кажется применимым при вычислении точечного произведения? Наверное, мне было бы интересно узнать, является ли это, как правило, проблемой в физическом движке и как она адресована.

Ответ 1

Один общий трюк состоит в том, чтобы сделать переменную аккумулятора типом с более высокой точностью, чем сами векторы.

В качестве альтернативы можно суммировать Кахан при суммировании терминов.

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

Разумеется, можно объединить оба вышеуказанных подхода.

Обратите внимание, что выше приведено общее поведение ошибок для точечных продуктов, а не только катастрофическое аннулирование.

Ответ 2

Вы говорите в комментарии, что вам нужно рассчитать x1 * x2 + y1 * y2, где все переменные являются поплавками. Поэтому, если вы выполняете вычисления с двойной точностью, вы не теряете никакой точности, потому что двойная точность имеет в два раза больше бит точности, чем float (при условии, что ваша цель использует IEEE-754).

В частности: пусть xx, yy - действительные числа, представляемые float переменными x, y. Пусть xxyy - их произведение, а xy - результат умножения двойной точности x * y. Тогда во всех случаях xxyy - действительное число, представленное xy.