BigDecimal 发挥 Java/Android 上 BigDecimal 的威力

问题描述 投票:0回答:4

我有一个简单的 BigDecimal,我想将其转换为另一个 BigDecimal,例如 11.11^-1.54。在 Java/Android 中最简洁的方法是什么?我不喜欢转换为双打的想法,因为它是用于医疗应用,所以我希望能有最大的精确度。到目前为止,我已经审查了 http://commons.apache.org/math/ 和 Google Guava 的数学内容,但什么也没找到。

编辑: 整个计算比较复杂,这样的运算很多。我最终需要尽可能多的精确度。

java android bigdecimal
4个回答
8
投票

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
投票

查看 “Java Number Cruncher:Java 程序员数值计算指南” - 第 12.5 章大十进制函数:有一些源代码具有尽可能精确的算法来计算指数和对数。

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

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


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.

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

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


2
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.