0

我必须找到对数,然后在对许多大十进制数进行几次计算后找到对数。由于 BigDecimal 数字不支持 log 和 antilog,为此我使用了 Apfloat 库并使用它的 pow 方法,该方法可以将两个参数作为 Apfloat 值,如下所示:

ApfloatMath.pow(Constants.BASE_OF_LOG, apFloatNum);

问题是我在循环中使用它并且循环很大。Apfloat pow 需要很长时间才能找到电源,超过一个小时。为了避免这种情况,我考虑将 Apfloat 转换为 double ,然后使用 Math.pow ,它运行速度很快,但对于几个值来说是无限的。

我应该怎么办?有谁知道 ApfloatMath.pow 替代方案?

4

1 回答 1

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安装,因此无法对此进行测试,因此您应该看看上述解决方案对您来说是否足够好(特别是如果它对您来说足够准确) ,如果它实际上比你拥有的更好/更快。

于 2018-04-28T17:35:12.330 回答