Java float unexpectedly rounded

2019-02-20 21:43发布

问题:

I'm using a float constant and setting a objects private float variable to the float constant below, but when the object outputs the value it was set to, it's rounding up the last digit in the float.

private final float RF_FREQUENCY = 956.35625f;
Object o = new Object();
o.setRFFrequency(RF_FREQUENCY);
System.out.println(o.getRFFrequency);

Output: 956.35626

The variable in the object is declared as protected float rfFrequency; and below are the getters and setters.

public float getRFFrequency() {
        return rfFrequency;
    }
public void setRFFrequency(float value) {
        this.rfFrequency = value;
    }

Any idea why this is happening?

回答1:

Because single precision IEEE754 floating point numbers only have 23 bits of precision (24 including the implicit 1 bit at the start).

That equates to roughly seven decimal digits and you can see that your number has eight digits in it.

All that's happening is that the computer is choosing the closest number to what you asked for that it can represent.

If you need more precision, use a double. That gives you 52/53 bits which equates to about 15 decimal digits.



回答2:

Floats can't represent every number, so numbers are rounded. Doubles are the same, but with a higher precision. If you use Double your output will be 956.35625 (in this special case).



回答3:

After some testing, I got this result:

final float RF_FREQUENCY = 956.35625f;
System.out.println(String.format("%.5f", RF_FREQUENCY));
final BigDecimal xRF_FREQUENCY = new BigDecimal(956.35625);
System.out.println(String.format("%.5f", xRF_FREQUENCY));

And the output was:

956,35626
956,35625

So, as its explained in more details from coderanch and in this blog post, I recommend you to change to BigDecimal.

EDIT: I've found another post about same problem in stackoverflow Double vs. BigDecimal? Hope it helps you.