我必须找到日志,然后在几次计算之后找到许多大十进制数的反对数。由于BigDecimal数字不支持log和antilog,为此我使用了Apfloat库并使用它的pow方法,它可以将两个参数作为Apfloat值,如下所示:
ApfloatMath.pow(Constants.BASE_OF_LOG,apFloatNum);
问题是我在循环中使用它并且循环很大。 Apfloat pow需要花费大量时间才能找到超过一小时的功率。为了避免这种情况,我想到将Apfloat转换为double,然后使用Math.pow,它运行速度很快,但是给了我很少的值。
我该怎么办?有谁知道ApfloatMath.pow替代?
答案 0 :(得分:0)
你说你现在正在使用Math.pow()
,而且有些调用会返回无限值。
如果您可以使用(远不那么准确)doubles
代替BigDecimals
,那么您应该想到数学,
x = Math.pow(a, x);
相当于
x = Math.pow(a, x - y) * Math.pow(a, y);
假设你有一个很大的价值,我们称之为big
,而不是做:
// pow(a, big) may return infinite
BigDecimal n = BigDecimal.valueOf(Math.pow(a, big));
你也可以这样做:
// do this once, outside the loop
BigDecimal large = BigDecimal.valueOf(a).pow(100);
...
// do this inside the loop
// pow(a, big - 100) should not return infinite
BigDecimal n = BigDecimal.valueOf(Math.pow(a, big - 100)).multiply(large);
而不是100,您可能想要选择另一个更适合您正在使用的值的常量。但是像上面的这样的东西可以是一个简单的解决方案,并且比你描述的要快得多。
对于大值,ApfloatMath.pow()
可能只会慢一些。如果是这种情况,您也可以将上述原则应用于Apfloat.pow()
。您只需要在循环外执行以下一次:
Apfloat large = ApfloatMath.pow(Constants.BASE_OF_LOG, 100);
然后你可以在循环中使用以下 :
x = ApfloatMath.pow(Constants.BASE_OF_LOG, big - 100).multiply(large);
在循环中。
但你必须测试是否能让事情变得更快。我可以想象,对于整数指数,ApfloatMath.pow()
可以快得多。
由于我对您的数据了解不多,而且我没有安装Apfloat
,因此我无法对此进行测试,因此您应该看看上述解决方案是否足够好你(特别是如果它足够准确),如果它实际上比你的更好/更快。