контроль переполнения и потери точности при умножении в два раза

Ques:

У меня есть большое число чисел с плавающей запятой (~ 10000 чисел), каждое из которых имеет 6 цифр после десятичной. Теперь умножение всех этих чисел даст около 60 000 цифр. Но двойной диапазон только для 15 цифр. Выходной продукт должен иметь 6 цифр точности после десятичной.

мой подход:

Я думал о том, чтобы умножить эти числа на 10 ^ 6, а затем умножить их и затем разделить на 10 ^ 12.

Я также думал о том, чтобы умножить эти числа, используя массивы для хранения их цифр, а затем преобразовать их в десятичную. Но это также кажется громоздким и может не дать правильного результата.

Есть ли альтернативный способ сделать это?

-2

Решение

Я думал о том, чтобы умножить эти числа на 10 ^ 6, а затем умножить их и затем разделить на 10 ^ 12.

Это только приведет к дальнейшей потере точности. В плавающей точке большие числа представлены примерно так же, как маленькие числа. Увеличение ваших чисел только означает, что вы делаете 19999 умножений (и одно деление) вместо 9999 умножений; он волшебным образом не дает вам более значимых цифр.

Эта манипуляция была бы полезна только в том случае, если бы она не позволяла частичному продукту проникать на субнормальную территорию (и в этом случае рекомендуется умножение на степень два, чтобы избежать потери точности из-за умножения). В вашем вопросе нет указаний на то, что это происходит, ни примерный набор данных, ни код, поэтому можно дать только общее объяснение ниже:

Умножение с плавающей запятой ведет себя очень хорошо, когда оно не переполняется или не переполняется. В первом порядке можно предположить, что относительные неточности складываются так, что умножение 10000 значений дает результат, который находится на расстоянии 9999 машинных эпсилон от математического результата в относительных единицах (*).

Решение поставленной задачи (без кода, без набора данных) заключается в использовании более широкого типа с плавающей точкой для промежуточных умножений. Это решает как проблемы недопущения, так и переполнения, а также дает относительную точность конечного результата, так что после округления до исходного типа с плавающей запятой продукт ошибочен не более чем одним ULP.

В зависимости от вашего языка программирования, такой более широкий тип с плавающей точкой может быть доступен как long double, Для 10000 умножений 80-битный «расширенный двойной» формат, широко доступный в процессорах x86, значительно улучшит ситуацию, и вы вряд ли увидите разницу в производительности, если ваш компилятор сопоставит этот 80-битный формат с плавающей запятой тип. В противном случае вам придется использовать программную реализацию, такую ​​как MPFR»s формат с плавающей запятой произвольной точности или двойной-двойной формат.

(*) На самом деле относительные неточности усугубляются, так что реальная оценка относительной погрешности больше похожа на (1 + ε)9999 — 1 где ε — эпсилон машины. Кроме того, в действительности относительные ошибки часто взаимно компенсируют друг друга, поэтому можно ожидать, что фактическая относительная ошибка будет расти как квадратный корень из теоретической максимальной ошибки.

2

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector