Java/Android 上的 BigDecimal 的幂运算

9
我有一个简单的BigDecimal,想要把它的幂运算到另一个BigDecimal上,例如11.11^-1.54。在Java/Android中最好的方法是什么?我不喜欢转换为double,因为这是医疗应用程序,所以我希望能够获得尽可能大的精度。到目前为止,我已经查看了http://commons.apache.org/math/和Google Guava的数学内容,但没有找到合适的解决方案。
编辑: 整个计算过程很复杂,并且有许多类似的操作。我需要尽可能多的精度。

部分重复了这个问题的内容。 - Geoffrey De Smet
4个回答

9

一个针对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许可证吗? - Geoffrey De Smet
有计划将该方法添加到Apache的commons-lang的NumberUtils或Google的guava中吗? - Geoffrey De Smet
@GeoffreyDeSmet 没有许可证,这只是一个实用类。 - softawareblog.com
没有许可证意味着它是专有的,不合法的重复使用或分发...只需应用Apache软件许可证、MIT或BSD,这些许可证对使用几乎没有任何限制。 - Geoffrey De Smet
1
这个类在进行计算时使用了 Thread.yield();,这在数学函数中是非常奇怪的事情。 - Roman
@softawareblog.com 这太棒了!为了使这段代码更易于使用,它需要进入Maven Central,但这需要很多繁琐的程序,可以通过将此代码添加到commons-lang的NumberUtils中,我们希望这样做(许可证允许我们这样做)。作为commons-lang的一部分,它将非常容易被消费,在maven central上得到同行评审,并对整个社区可见。当然,我们会保留作者标签以给予您荣誉。 - Geoffrey De Smet

4

你需要多少位数的精度?你的示例中只使用了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.

对于你的设备来说,这可能仍然足够快。

我没有包含代码,部分原因是它非常长。我对其速度感到印象深刻。 ;)


尽可能精确。计算本身很复杂,并且有许多操作。双精度浮点数是获得它的最佳方式吗?在复杂计算结束时将其四舍五入到所需精度。 - Elchin
如果您真的不知道需要多少精度,而性能也不是问题,我建议使用BigDecimal。 - Peter Lawrey
1
谢谢提供库链接!我想现在会选择double,不过BigDecimal方法非常有用!我只是想知道为什么Apache Commons Math没有包含它。 - Elchin
1
链接到该库已失效。作者书籍页面在这里 - MT0

4

请参阅"Java Number Cruncher: The Java Programmer's Guide to Numerical Computing"-第12.5章BigDecimal函数:其中包含尽可能精确的算法源代码,可用于计算指数和对数。

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

然而,双精度浮点数具有很好的精度,我强烈建议您测试一下是否足够满足您的需求。


2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接