0

我在这里和那里阅读了有关如何处理大数字的解释,似乎同一个类 BigNumber 也可以用于非常小的数字。

但是,我无法弄清楚如何在不丢失精度的情况下使其工作。

我有像 0.0000000000012 这样的数字,我想在一个等式中使用,但我不知道如何用 BigNumber 创建这个数字(如果那是我应该使用的),然后当我把它变成一个 double 使用时如何避免失去精度在我的等式中。

我是否应该将 hte 方程中使用的每个数字都作为 BigDecimal(即使是具有简单值(12、0.1、...)或只有 0.0000000000012 的数字也应该是 BigNumber,并且我可以确定我不会丢失精度?

预先感谢您的帮助,问候,B.

4

3 回答 3

4

使用类BigDecimal。它可以用来表示任意精度的十进制数。要从太精确而无法用双精度表示的文字创建 BigDecimal,请使用字符串构造函数:

BigDecimal almostOne = new BigDecimal("0.999999999999999999999999999999999999999987", MathContext.UNLIMITED);

当您将它们转换为双精度时,您会失去精度。因此 BigDecimal 类有多种方法可以在保持精度的同时执行基本算术:

BigDecimal exactlyTen = new BigDecimal(10);
BigDecimal almostTen = almostOne.multiply(exactlyTen);

当您的代码对性能至关重要时,我建议您将问题“ What to do with Java BigDecimal performance? ”作为进一步阅读。

于 2013-06-19T12:24:04.590 回答
3
String number = "0.0000000000012";

BigDecimal decimal = new BigDecimal(number);
System.out.println(decimal.toString());
decimal = decimal.multiply(new BigDecimal(1000000000000L));
System.out.println(decimal.toString());

这是您如何使用和测试 BigDecimal Number 运行此代码的代码。Fir sysout 将返回1.2E-12,即等于 0.0000000000012。要对此进行测试,请将其与 1000000000000 结果相乘到 1.2。这意味着您不会失去精确度。

于 2013-06-19T12:25:30.620 回答
0

除非您有超过 15 个有效数字的精度,否则您不必使用 BigDecimal。您确实必须使用适当的舍入,这是 BigDecimal 可以帮助您解决的问题,但这并不意味着您不能对 double 做同样的事情。

double d = 0.0000000000012;
BigDecimal bd = BigDecimal.valueOf(d);
System.out.println("before d: " + d + " bd: " + bd);
d *= 1000000000000L;
d = Math.round(d * 1e2) / 1e2; // round to two places
bd = bd.multiply(BigDecimal.valueOf(1000000000000L));
System.out.println("after d: " + d + " bd: " + bd);

印刷

before d: 1.2E-12 bd: 1.2E-12
after d: 1.2 bd: 1.2000000000000

在性能方面,性能提高doubleBigDecimal100 倍。BigDecimal 也会产生大量垃圾,而 double 不会产生任何垃圾。创建大量垃圾不仅速度很慢,而且会通过用垃圾填充 CPU 缓存来减慢所有其余代码的速度。

当我将它变成双精度以在我的方程中使用时如何避免失去精度。

使用 double 您需要自己跟踪精度。仅当您的函数不知道精度并且您无法告诉它们并且需要传递值时,这才是一个问题。即你没有机会四舍五入的答案。

于 2013-06-19T13:05:52.770 回答