-2

QUES:控制精度溢出和损失,同时乘以双打

我有大量浮点数(〜万数),小数点后各自具有6位数字。现在,所有这些数字的乘法将产生大约60,000个数字。但双倍范围仅适用于15位数字。输出产品必须在小数点后有6位精度。

我的方法:

我想10^6这些数字相乘,然后将它们相乘,后来由10^12分他们。

我也想过用这些数字乘以数组来存储它们的数字,然后把它们转换成十进制数。但是这也看起来很麻烦并且可能不会产生正确的结果。

有没有更容易的方法来做到这一点?

+0

我为我的代码使用C++。 :) – bnks452

+0

http://stackoverflow.com/q/2568446/327083 –

+0

http://www.google.com/search?q=c%2B%2B+arbitrary+precision –

回答

2

我想这些数字乘以10^6,然后乘以它们,然后再除以10^12。

这只会进一步降低准确性。在浮点数中,大数表示大致与小数字一样。只让你的数字更大意味着你正在做19999乘法(和一个除法)而不是9999乘法;它不会神奇地给你更有意义的数字。

该操作只有在防止部分产品进入低于正常范围的情况下才有用(在这种情况下,建议乘以2的幂数以避免由于乘法导致的准确度损失)。在你的问题中没有迹象表明会发生这种情况,没有示例数据集,也没有代码,所以只能提供下面的通用解释:

浮点乘法在不下溢或溢出时表现非常好。在第一阶中,你可以假设相对误差加起来,所以乘以10000的值产生的结果是相对于(*)数学结果的9999个机器。

上述问题的解决方案(无代码,无数据集)是对中间乘法使用更宽泛的浮点类型。这既解决了下溢或溢出的问题,又为最终结果留下了相对的准确性,从而一旦舍入到原始浮点类型,该产品最多只能有一个ULP出错。

根据您的编程语言,这种更宽的浮点型may be available aslong double。对于10000次乘法,在x86处理器中广泛使用的80位“扩展双倍”格式将显着改善事情,只要您的编译器将此80位格式映射到浮点,您几乎不会看到任何性能差异类型。否则,您将不得不使用软件实现,例如MPFR'的任意精度浮点格式或double-double格式。 (*)实际上,相对误差是复合的,因此相对误差的实际界限更像(1 +ε),其中ε是机器的ε值。而且,实际上,相对误差通常会相互抵消,因此您可以预期实际相对误差会像理论最大误差的平方根那样增长。

+0

“这种操作只会有用,如果它防止部分产品进入低于正常范围(在这种情况下,建议乘以2的幂数以避免由于乘法导致的精度损失)。“你能解释一下这是什么意思吗? – bnks452

+0

@ bnks452如果你提供了一个示例数据集,我会更喜欢它,我可以告诉你,你不需要担心子异常。否则,在这里有一个定义(https://en.wikipedia.org/wiki/Denormal_number),与讨论相关的句子是“它允许计算在结果很小时缓慢地失去精度”,含义尽管你没有得到零,但当一个部分产品是一个低于正常的数字时,最终的结果可能不如预期的那么准确。 –

+0

将数字乘以10^6我的意思是将它们存储为整数并相乘,因为我的数据集由浮点数< 1 and > 0和小数点后6位数组成。例如:0.123456,0.986173等等。大约有10000个这样的数字,我必须在小数点后得到6位数的输出。 – bnks452