0

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?

mskfisher
  • 3,291
  • 4
  • 35
  • 48
TyC
  • 792
  • 6
  • 11
  • 23

3 Answers3

3

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.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • So how would one go about still using a float and outputting the intended value - 956.25625? – TyC Feb 17 '12 at 14:15
  • One wouldn't with a `float` but, if by "float" you meant general floating point rather than specific type, one could use a `double`. – paxdiablo Feb 17 '12 at 14:16
  • 1
    @TyC `final float RF_FREQUENCY = 956.35625f; System.out.println(String.format("%.5f", RF_FREQUENCY));` – Luiggi Mendoza Feb 17 '12 at 14:18
  • 1
    ...That is to say, @TyC, that you really can't. You can't store `956.25625` in a `float` without getting it rounded to the nearest _binary fraction_ with 23 bits of precision. – Louis Wasserman Feb 17 '12 at 17:09
  • You simply can't put 26 bits into 23. Until it is float, not rar archive. – Gangnus Mar 05 '12 at 20:43
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).

AlexS
  • 5,295
  • 3
  • 38
  • 54
1

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.

Community
  • 1
  • 1
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • I would use BigDecimal only if a double doesn't provide the required precision (for example cryptographic algorithms). I haven't tested, but I'm sure computations on BigDecimal are more expensive than computations on double (especially on 64bit machines). – AlexS Feb 18 '12 at 13:01