问题
I have a double var
public double votes(){
double votexp = 0;
for(Elettore e:docenti.values()){
if(e.getVoto()==true) //everytime this is true increment by 1
{
votexp+=1.0;
}
}
for(Elettore e:studenti.values()){
if(e.getVoto()==true) //everytime this is true increment by 0.2
{
votexp+=0.2;
}
}
for(Elettore e:pta.values()){
if(e.getVoto()==true) //everytime this is true increment by 0.2
{
votexp+=0.2;
}
}
return votexp;
}
In my case the variable shoud be incremented to 2.6 but votexp returns 2.6000000000000005 how can i fix this by using the same double var and return a double precision number ?
回答1:
You are accumulating a rounding error. The simplest thing to do is to use an long
(or int
and only use a double at the end. (Or a BigDecimal and double at the end, but this is overly complicated)
public double votes() {
long votexp = 0;
for (Elettore e : docenti.values())
if (e.getVoto()) //everytime this is true increment by 1
votexp += 10;
for (Elettore e : studenti.values())
if (e.getVoto()) //everytime this is true increment by 0.2
votexp += 2;
for (Elettore e : pta.values())
if (e.getVoto()) //everytime this is true increment by 0.2
votexp += 2;
return votexp / 10.0;
}
double a = 26 / 10.0;
System.out.println(a);
prints
2.6
As the Double.toString() "knows" values can be imprecise, it will do a small amount of rounding. This rounding is limited so the result of operating on two double
can have an error too large to hide. If you round your last result correctly, the error will be small enough it won't cause a problem.
回答2:
Try using java.math.BigDecimal class.
回答3:
Some numbers cannot be represented by double-precision floating point format exactly. Looks like an intermediate number in your calculation has this flaw, which is included in the final result.
回答4:
You could try this
(double)Math.round(value * 10) / 10
but you will never get the good result by doing addition of doubles like this
回答5:
You have to round the result, floating point numbers in Java (and basically every other environment) are not perfect, and sometimes small inaccuracies creep in.
If you're dealing with decimal numbers, there's BigDecimal, which can precisely represent what you've shown (it just can't precisely represent other things, like 1 / 3
).
Alternately, you can multiply by 10, use Math.round
, and divide by 10
if the problem isn't with the actual end value, but with inaccuracies that have crept in during the time you've built up that value. That happens to be case with 2.6 built up like this:
double n = 0;
n += 1;
n += 0.2;
n += 1;
n += 0.2;
n += 0.2;
System.out.println("n = " + n); // "2.6000000000000005"
n = (double)Math.round(n * 10) / 10;
System.out.println("n = " + n); // "2.6"
...but I don't think there's a guarantee that it will necessarily be the case with all values. (I'm not a floating point guru.)
Or just worry about it when you do the output, by truncating the output result to the appropriate level of precision.
来源:https://stackoverflow.com/questions/9413908/java-double-increment