Подтвердить что ты не робот

С++: стратегии устойчивости арифметики с плавающей запятой

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

Пример: предположим, что вы хотели бы суммировать вектор/массив в миллион 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 бит, но те же проблемы все еще применяются.

В основном я интересуюсь:

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

Ответ 1

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

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

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

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