我有一个关注精度损失的问题
我的任务是将数字打印为字符串
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), 但我认为这不是好方法
答案 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