如何使用非常小的浮点数而不会出现精度损失?

时间:2013-06-19 12:17:28

标签: java

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

然而,我无法弄清楚如何在不失去精确度的情况下使其发挥作用。

我想在公式中使用0.0000000000012之类的数字,但我不知道如何用BigNumber创建这个数字(如果那是我应该使用的那个),那么当我把它变成一个时,如何避免失去精度在我的等式中使用加倍。

我应该将hte方程中使用的每个数字都作为BigDecimal(即使是具有简单值(12,0.1,...)或仅0.0000000000012的数字应该是BigNumber,我可以肯定我不会失去精度吗?

提前感谢您的帮助, 问候, 乙

3 个答案:

答案 0 :(得分:4)

使用课程BigDecimal。它可用于表示任意精度的十进制数。 要从文字中创建一个太精确而不能用double表示的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?”作为进一步阅读。

答案 1 :(得分: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。这意味着你不会失去精确度。

答案 2 :(得分: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

在效果double方面,BigDecimal执行{{1}}的因数为100倍。 BigDecimal也会产生大量垃圾,而double则不会产生任何垃圾。创建大量垃圾不仅速度慢,而且通过向CPU缓存中填充垃圾来减慢所有其余代码的速度。

  

当我把它变成一个双精度来使用时,如何避免失去精度。

使用double,您需要自己跟踪精度。如果您的函数不知道精度并且您无法告诉它们并且需要传递该值,那么这只是一个问题。即你没有机会完成答案。