Double increments in Java [duplicate]

2019-02-13 17:09发布

问题:

Possible Duplicate:
How to iterate between 0.1f and 1.0f with 0.1f increments in Java?

Part of my program needs to use values inside a while loop as:

0.1

0.2

0.3

...

0.9

so I need to provide them inside that loop. Here is the code:

double x = 0.0;
while ( x<=1 )
{
// increment x by 0.1 for each iteration
x += 0.1;
}

I need the output to be EXACTLY:

0.1

0.2

0.3

0.4

0.5

0.6

0.7

0.8

0.9

But it actually gives me something like:

0.1

0.2

0.300000000000000000000000004

0.4

0.5

0.6

0.79999999999999999999999999

0.89999999999999999999999999

0.99999999999999999999999999

回答1:

Welcome to the world of floating point, where 0.1 isn't 0.1. The problem is that many numbers, including 0.1, cannot be represented exactly in a double. So you aren't really adding exactly 0.1 to x each time through the loop.

One approach is to use integer arithmetic and divide by 10:

int i = 0;
while (i <= 10) {
    double x = i / 10.0;
    . . .
    i++;
}

Another approach is to make x a BigDecimal, where you can specify that you want a particular precision. It basically is doing what the above loop does (an integer plus a scale), but packaged up in a nice class with lots of bells and whistles. Oh, and it has arbitrary precision.



回答2:

To get output you want, you could use DecimalFormat. Here is some sample code.

import java.text.DecimalFormat;

public class DF {

  public static void main(String [] args) {

    double x = 0.1;
    DecimalFormat form = new DecimalFormat("#.#");
    while (x <= .9) {
      System.out.println(Double.valueOf(form.format(x)));
      x += 0.1;
    }

  }

}

As far as the implementation you have now, there is no guarantee as to the precision of what gets printed due to the nature of floating point numbers.



回答3:

Using BigDecimal

double x = 0.0;
   int decimalPlaces = 2;           

  while ( x<=1 )
  {

    x += 0.1;
    BigDecimal bd = new BigDecimal(x);
    bd = bd.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP);
    x = bd.doubleValue();           

    System.out.println(x); 
  }


回答4:

you need to use the decimal formatter to get the expected output.

Below is the code for generating the expected output:

import java.text.DecimalFormat;


public class FloatIncrement {

    public static void main (String args[]){

        double x= 0.0;
        DecimalFormat form = new DecimalFormat("#.#");      
        while(x<0.9){
            x= x+0.1;
            System.out.println("X : "+Double.valueOf(form.format(x)));          

        }

    }
}


回答5:

That's because you can use binary floating point to do precise decimal arithmetic because FP cannot precisely represent all decimal values.

You need to use an integer value representing some decimal fractional unit like hundredths or thousandths or use something like BigDecimal.



回答6:

Double is stored in binary

float and double store numbers as a certain number of significant figures and a radix point (kind of like scientific notation). The significant figures part is not always perfect, because it's stored as a certain number of binary digits - so you can't expect it to perform the way you're expecting it to. (for a better explanation see http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html)

Consider using a class such as BigDecimal or a class that implements rational numbers, like the ones mentioned here - Is there a commonly used rational numbers library in Java?

You could also just turn i into an integer, and change it from 1 to 10, and compensate for this in your code.