我有一个简单的 BigDecimal,我想为另一个 BigDecimal 供电,例如 11.11^-1.54。在 Java/Android 中最简洁的方法是什么?我不喜欢转换为双打的想法,因为它是用于医疗应用的,所以我会很感激可能的最大精度。到目前为止,我已经查看了来自 Google Guava 的http://commons.apache.org/math/和数学资料,但一无所获。
编辑:整个计算很复杂,并且有很多这样的操作。最后我需要尽可能多的精确度。
我有一个简单的 BigDecimal,我想为另一个 BigDecimal 供电,例如 11.11^-1.54。在 Java/Android 中最简洁的方法是什么?我不喜欢转换为双打的想法,因为它是用于医疗应用的,所以我会很感激可能的最大精度。到目前为止,我已经查看了来自 Google Guava 的http://commons.apache.org/math/和数学资料,但一无所获。
编辑:整个计算很复杂,并且有很多这样的操作。最后我需要尽可能多的精确度。
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 );
您需要多少位数的精度?您在示例中仅使用 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.
在您的设备上可能仍然足够快。
我没有包含代码,部分原因是它很长。我对它的速度印象深刻。;)
查看“Java Number Cruncher: The Java Programmer's Guide to Numerical Computing” - 第 12.5 章 Big Decimal Functions:有一些源代码具有尽可能精确的算法来计算指数和对数。
使用数学公式: x^y=exp(y*ln(x)) 您可以获得最高精度的结果。
尽管如此,双打确实具有良好的精度,我强烈建议您测试它是否不够精确以满足您的需要。
有一个很好的库 ApFloat: http: //www.apfloat.org/