简体   繁体   English

Java精度损失

[英]Java loss of precision

I have a problem concerned with losing of precision 我有一个关于精度损失的问题

my task is to print numbers as strings 我的任务是将数字打印为字符串

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);

for example, 0.2*7=1.4000000000000001; 例如0.2 * 7 = 1.4000000000000001; 0.0000014/10=1.3999999999999998E-7 0.0000014 / 10 = 1.3999999999999998E-7

how to figure out this problem? 如何解决这个问题?

UPD : The main problem is string output formating. UPD :主要问题是字符串输出格式。 i don't bother about losting of about 0.00000001 value. 我不担心丢失约0.00000001的值。 Now I solved it as String.format("%f", value), but I think it's not good approach 现在,我将其解析为String.format(“%f”,value),但我认为这不是一个好方法

As mentioned by others you have to use java.math.BigDecimal instead of float/double. 正如其他人所提到的,您必须使用java.math.BigDecimal而不是float / double。 This however comes with its own set of problems. 但是,这有其自身的一系列问题。

For instance when you call BigDecimal(double) the value you pass in will be expanded to its full representation: 例如,当您调用BigDecimal(double)时,您传入的值将扩展为其完整表示形式:

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

But when you use the BigDecimal(String) constructor the eact value is represented and you get 但是,当您使用BigDecimal(String)构造函数时,会表示eact值,并且您得到

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

You can read more on BigDecimal's limitations in Joshua Bloch and Neal Gafter's splendid Java puzzlers book and in this informative article. 您可以在Joshua Bloch和Neal Gafter的出色的Java益智类书籍以及这篇内容丰富的文章中了解有关BigDecimal限制的更多信息。 Finally note that toString on BigDecimal's will print in scientific notation so you will properly have to use toPlainString instead. 最后请注意,BigDecimal上的toString将以科学计数法打印,因此您必须正确地使用toPlainString

The double type does not have infinite precision and cannot represent decimals exactly. double类型没有无限的精度,不能精确地表示小数。 You are observing normal rounding errors. 您正在观察正常的舍入错误。 For arbitrary precision arithmetic, you will need to use java.math.BigDecimal instead. 对于任意精度算术,您将需要使用java.math.BigDecimal代替。

Search for "floating point numbers" on SO and you'll get a slew of answers as to why this happens. 在SO上搜索“浮点数”,您将获得大量答案,了解发生这种情况的原因。 It has to do with how floating point numbers are represented in computers. 它与计算机中浮点数的表示方式有关。

How is floating point stored? 浮点如何存储? When does it matter? 什么时候重要?

Another article on the matter - Floating Point Approximation 关于此问题的另一篇文章- 浮点近似

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM