Я думал о умножении этих чисел на 10^6, а затем их умножении и последующем их делении на 10^12.
Это приведет только к дальнейшей потере точности. В плавающей точке большие числа представлены примерно так же, как небольшие числа. Увеличение числа ваших чисел означает, что вы делаете 19999 умножений (и одно деление) вместо 9999 умножений; это не волшебным образом дает вам более значимые цифры.
Эта манипуляция была бы полезной только в том случае, если бы это предотвратило попадание частичного продукта в субнормальную территорию (и в этом случае рекомендуется умножить на две силы, чтобы избежать потери точности из-за умножения). В вашем вопросе нет никаких указаний на то, что это происходит, нет набора данных примера, никакого кода, поэтому можно предоставить общее объяснение ниже:
Умножение с плавающей запятой очень хорошо ведет себя, когда оно не переполняется или переполняется , В первом порядке вы можете предположить, что относительные неточности складываются, так что умножение значений 10000 дает результат, который 9999 машинных эпсилонов от математического результата в относительных терминах (*).
Решение проблемы, как указано (без кода, без набора данных), заключается в использовании более широкого типа с плавающей запятой для промежуточных умножений. Это решает проблемы с потоком или переполнением и дает вам относительную точность в конечном результате, так что после округления до исходного типа с плавающей запятой продукт не соответствует не более чем одному ULP.
В зависимости от вашего языка программирования такой более широкий тип с плавающей запятой may be available aslong double
. Для 10000 умножений 80-разрядный «расширенный двойной» формат, широко доступный в x86-процессорах, значительно улучшит ситуацию, и вы вряд ли увидите разницу в производительности, если ваш компилятор сопоставляет этот 80-битный формат с плавающей точкой тип. В противном случае вам придется использовать программную реализацию, такую как MPFR' с произвольной точностью с плавающей запятой или двойной двойной формат.
(*) В действительности относительные погрешности соединены так, что реальная оценка относительной погрешности больше похожа на (1 + ε) - 1 где ε - эпсилон машины. Кроме того, в действительности относительные ошибки часто отменяют друг друга, так что вы можете ожидать, что фактическая относительная ошибка будет расти как квадратный корень теоретической максимальной ошибки.
Я использую C++ для своего кода. :) – bnks452
http://stackoverflow.com/q/2568446/327083 –
http://www.google.com/search?q=c%2B%2B+arbitrary+precision –