Java精度损失

时间:2010-03-05 19:38:25

标签: java string precision

我有一个关注精度损失的问题

我的任务是将数字打印为字符串

int exponent = ...
int[] Mantissas = { 1, 2, 5 };
double dataStep = java.lang.Math.pow(10.0, exponent) * Mantissas[mantissaIndex];
...
for (int i = 0; i < NSteps; i++)
                    steps[i] = firstStep + i * dataStep;
draw(steps);
例如,

,0.2 * 7 = 1.4000000000000001; 0.0000014 / 10 = 1.3999999999999998E-7

如何弄清楚这个问题?

UPD :主要问题是字符串输出格式化。我不打扰约0.00000001值的损失。 现在我把它解决为String.format(“%f”,value), 但我认为这不是好方法

3 个答案:

答案 0 :(得分:3)

正如其他人所说,你必须使用 java.math.BigDecimal 而不是float / double。然而,这有其自身的一系列问题。

例如,当您调用BigDecimal(double)时,传入的值将扩展为其完整表示形式:

BigDecimal oneTenth = new BigDecimal(0.1);
BigDecimal oneMillion = new BigDecimal(1000000);
oneTenth.multiply(oneMillion)
out> 100000.0000000000055511151231257827021181583404541015625000000

但是当你使用BigDecimal(String)构造函数时,表示了eact值,你得到了

BigDecimal oneTenth = new BigDecimal("0.1");
BigDecimalr oneMillion = new BigDecimal(1000000);
oneTenth.multiply(oneMillion)
out> 100000.0

你可以阅读更多关于BigDecimal在Joshua Bloch和Neal Gafter的精彩Java puzzlers书以及this内容丰富的文章中的局限性。最后请注意,BigDecimal上的toString将以科学记数法打印,因此您必须使用 toPlainString

答案 1 :(得分:2)

double类型没有无限精度,并且不能完全表示小数。您正在观察正常的舍入错误。对于任意精度算术,您将需要使用java.math.BigDecimal。

答案 2 :(得分:1)

在SO上搜索“浮点数”,你会得到一些关于为什么会发生这种情况的答案。它与浮点数如何在计算机中表示有关。

How is floating point stored? When does it matter?

关于此事的另一篇文章 - Floating Point Approximation