【问题标题】:BigDecimal to the power of BigDecimal on Java/AndroidJava/Android 上 BigDecimal 的强大功能
【发布时间】:2012-08-07 15:09:05
【问题描述】:

我有一个简单的 BigDecimal,我想为另一个 BigDecimal 供电,例如 11.11^-1.54。在 Java/Android 中最简洁的方法是什么?我不喜欢转换为双打的想法,因为它是用于医疗应用的,所以我会很感激可能的最大精度。到目前为止,我已经查看了来自 Google Guava 的 http://commons.apache.org/math/ 和数学资料,但一无所获。

编辑: 整个计算很复杂,有很多这样的操作。最后我需要尽可能精确。

【问题讨论】:

标签: java android bigdecimal


【解决方案1】:

BigDecimal https://github.com/tareknaj/BigFunctions 的实用程序类

z = x^y 的例子 --> z = exp ( ln(x) * y )

final int SCALE = 10;
BigDecimal x = new BigDecimal(1);
BigDecimal y = new BigDecimal(12);

BigDecimal z = BigFunctions.exp( BigFunctions.ln(x, SCALE).multiply(y),SCALE );

【讨论】:

  • 许可证是什么?有没有机会获得 Apache 许可证?
  • 是否计划将该方法添加到 Apache 的 commons-lang 的 NumberUtils 或 Google 的 guava 中?
  • @GeoffreyDeSmet 没有许可证,它只是一个实用程序类
  • 没有许可证意味着重复使用或分发它是专有和非法的......只需申请 Apache 软件许可证、MIT 或 BSD,它们对使用几乎没有任何限制。
  • 这个类在进行计算时使用Thread.yield();,这是一个在数学函数中非常奇怪的东西。
【解决方案2】:

查看"Java Number Cruncher: The Java Programmer's Guide to Numerical Computing" - 第 12.5 章大十进制函数:有一些源代码具有尽可能精确的算法来计算指数和对数。

使用数学公式:x^y=exp(y*ln(x)),您可以获得最高精度的结果。

尽管如此双打确实有很好的精度,我强烈建议您测试一下它是否不够精确以满足您的需要。

【讨论】:

    【解决方案3】:

    您需要多少位数的精度?您在示例中仅使用 4 位数字。如果这是医学的并且适用于现实世界,那么您只能将现实世界中的大多数事物测量到 10-13 位数的准确度,而 double 的准确度最高可以达到 16 位数。

    System.out.println(Math.pow(11.11, -1.54));
    

    打印

    0.024524510581710988
    

    如果你使用本书中的图书馆http://www.apropos-logic.com/nc/,你可以获得

    int runs = 10000;
    
    long start = System.nanoTime();
    double x1 = 0;
    for (int i = 0; i < runs; i++)
        x1 = Math.pow(11.11, -1.54);
    long time = System.nanoTime() - start;
    System.out.println(x1 + " took " + time / runs / 1e3 + " us avg.");
    
    long start2 = System.nanoTime();
    BigDecimal x2 = null;
    for (int i = 0; i < runs; i++)
        x2 = exp(ln(BigDecimal.valueOf(11.11), 20).multiply(BigDecimal.valueOf(-1.54)), 20);
    long time2 = System.nanoTime() - start2;
    System.out.println(x2 + " took " + time2 / runs / 1e3 + " us avg.");
    

    打印(我们为微秒)

    0.024524510581710988 took 0.478 us avg.
    0.02452451058171098739 took 603.769 us avg.
    

    40位精度

    0.0245245105817109873886495555036930857940 took 1409 us avg.
    

    在您的设备上可能仍然足够快。

    我没有包含代码,部分原因是它很长。我对它的速度印象深刻。 ;)

    【讨论】:

    • 尽可能精确。计算本身很复杂,并且有许多这样的操作。双倍是获得它的最佳方式吗?在复杂计算结束时将其四舍五入到必要的精度。
    • 如果你真的不知道你需要多少精度并且性能不是问题,我会使用 BigDecimal。
    • 感谢图书馆链接!我想我现在会选择 double,但是 BigDecimal 方法非常有用!我只是想知道 Apache Commons Math 怎么没有包含它。
    • 图书馆链接已失效。这本书的作者页面是here
    【解决方案4】:

    有一个很好的库 ApFloat:http://www.apfloat.org/

    【讨论】:

      猜你喜欢
      • 2012-05-30
      • 2016-10-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-23
      • 1970-01-01
      • 1970-01-01
      • 2011-07-13
      • 1970-01-01
      相关资源
      最近更新 更多