Java精度损失

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

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

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),但我认为这不是好方法

正如其他人所提到的,你必须使用java.math.BigDecimal而不是float / double。 然而,这带来了一系列问题。

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

 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益智游戏书以及这篇内容丰富的文章中的局限性。 最后请注意,BigDecimal上的toString将以科学记数法打印,因此您必须使用toPlainString

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

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

浮点是如何存储的? 什么时候重要?

关于此事的另一篇文章 – 浮点近似