2012-06-29 3 views
10

Может ли кто-нибудь рекомендовать любые библиотеки/подпрограммы/пакеты C++, содержащие стратегии для поддержания стабильности различных операций с плавающей запятой?C++: стратегии стабильности арифметики с плавающей запятой

Пример: предположим, что вы хотите суммировать вектор/массив из миллиона long double в единичном интервале (0,1) и чтобы каждое число было примерно того же порядка величины. Наивное суммирование for (int i=0;i<1000000;++i) sum += array[i]; ненадежно - для достаточно больших i, sum будет иметь значительно больший порядок, чем array[i], и поэтому sum += array[i] будет эквивалентно sum += 0.00. (Примечание: решение этого примера представляет собой двоичную стратегию суммирования.)

Имею дело с суммами и произведениями тысяч/миллионов наименьших вероятностей. Я использую библиотеку произвольной точности MPFRC++ с существенным значением 2048 бит, но те же проблемы все еще применяются.

Я в основном озабочен:

  1. стратегий для точного суммирования много чисел (например, выше примера).
  2. Когда умножение и деление потенциально нестабильны? (Если я хочу, чтобы нормализовать большой массив чисел, что должно моя постоянная нормировки быть? Наименьшее значение? Крупнейшее? Медиана?)

ответ

6

Binary суммирование не гарантия точный результат. Самый надежный (хотя и медленный) метод заключается в использовании Kahan summation. Boost.Accumulators имеет реализацию выше и многое другое.

Умножение и стабильность деления: если вы не получаете денормализованных поплавков, они не страдают от тех же проблем, что и суммирование и вычитание. На самом деле ошибка умножения равна не более 0,5 ulp (единицы последнего места).

... Какова должна быть моя нормализация константы?

Что вы подразумеваете под "нормализацией"? Это зависит от используемого вами norm. Возможные кандидаты: используйте максимальное абсолютное значение в массиве или любое другое обобщенное среднее значение. (Другие варианты, которые вы указали, не работают, так как они могут быть равны нулю даже для ненулевого массива.)

+0

«Нормализовать», я имею в виду: На шаге X у меня есть набор миниатюрных, но ненулевых вероятности. На шаге X + 1 я умножу эти числа на еще более мелкие вероятности. Согласно деталям моей математической модели, я могу умножить числа на шаге X на любую константу (т.е. нормализовать) до перехода на шаг X + 1. Это имеет практическое преимущество, помогая избежать недоиспользования. – cmo

+0

@CycoMatto: тогда вы должны умножаться на мощность два раза в секунду. Единственный способ избежать переполнения/переполнения - гарантировать, что отношение между самым большим и наименьшим числами представляется с плавающими точками (если нет, вы ничего не можете сделать). – ybungalobill

+0

Альтернативно хранить свои логарифмы и использовать суммирование. Однако не могу сказать об устойчивости этого подхода. – ybungalobill