当前位置:  开发笔记 > 编程语言 > 正文

如何处理接近1的数字乘法

如何解决《如何处理接近1的数字乘法》经验,为你挑选了2个好方法。

我有一堆浮点数(Java双打),其中大部分都非常接近1,我需要将它们相乘作为更大计算的一部分.我需要做很多事情.

问题是虽然Java双打没有问题,例如:

0.0000000000000000000000000000000001 (1.0E-34)

它们不能代表以下内容:

1.0000000000000000000000000000000001

因此,我迅速失去了精确度(对于Java的双打,限制似乎约为1.000000000000001).

我考虑过只存储减去1的数字,所以例如1.0001将被存储为0.0001 - 但问题是再次将它们相乘我必须加1并且此时我失去了精度.

为了解决这个问题,我可以使用BigDecimals来执行计算(转换为BigDecimal,添加1.0,然后相乘),然后转换回双精度,但我对此的性能影响有严重的担忧.

任何人都可以看到一种避免使用BigDecimal的方法吗?

为清晰起见进行编辑:这是针对大规模协同过滤器,采用梯度下降优化算法.准确性是一个问题,因为协作过滤器通常处理非常小的数字(例如,人们点击产品广告的概率,可能是1000分之一,或10000分之一).

速度是一个问题,因为协作过滤器必须在数千万个数据点上进行训练,如果不是更多的话.



1> David Z..:

是的,因为

(1 + x) * (1 + y) = 1 + x + y + x*y

在你的情况,x并且y非常小,所以x*y将是较小-路太小,影响你的计算结果.所以就你而言,

(1 + x) * (1 + y) = 1 + x + y

这意味着您可以存储减去1的数字,而不是相乘,只需将它们相加即可.只要结果总是远小于1,它们就足够接近数学上精确的结果,你不会关心差异.

编辑:刚刚注意到:你说他们中的大多数非常接近1.显然,这种技术不适用于不接近1的数字 - 即,如果x并且y很大.但如果一个很大而一个很小,它可能仍然有效; 你只关心产品的大小x*y.(如果两个数字都不接近1,你可以使用常规的Java double乘法......)



2> v3...:

也许你可以使用对数?

对数方便地减少乘法到加法.

另外,为了处理初始精度损失,还有函数log1p(至少它存在于C/C++中),它返回log(1 + x)而没有任何精度损失.(例如log1p(1e-30)为我返回1e-30)

然后你可以使用expm1来获得实际结果的小数部分.

推荐阅读
贴进你的心聆听你的世界
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有