0

I'm having an issue with the rounding of a float value.

The following code gives me the following result:

public class ProductOrder {

  public static void main(String[] args) {
    int q = 48;
    float p = 6.95f;

    System.out.println(q * p);
  }

------
Output: 333.59998

While the expected result should be 333.6

When I replace q with 49 then its okay and i get 340,55

wvp
  • 1,134
  • 5
  • 15
  • 28
  • 1
    why "without `BigDecimal`"? This kind of situation is precisely what it's for (pun intended). – DannyMo Aug 05 '13 at 19:00

4 Answers4

2

As already pointed out, BigDecimal is designed for situations in which exact handling of short decimal fractions is especially important, and is much better for those situations than any binary floating point format.

The second best solution is to work in e.g. integer number of cents, and insert the decimal point only during display.

If you must use binary floating point, double is usually a better choice than float unless you are dealing with a lot of numbers and know float has enough precision.

For output, if you expect a result with e.g. no more than 2 decimal digits after the decimal point, you can use a DecimalFormat to round accordingly:

import java.text.DecimalFormat;

public class Test {
  public static void main(String[] args) {
    DecimalFormat df = new DecimalFormat("#0.##");
    int q = 48;
    float p = 6.95f;
    System.out.println(df.format(q * p));
  }
}

prints 333.6

Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75
0

The default formatting produces the least number of digits that are necessary to tell the number from from its neighbours. This means that if the result is even slightly off because of roundoff error you will get the "ugly" output.

One way to deal with this is using exact arithmetic (BigDecimal or integer arithmetic). Another is rounding the output, for example:

System.out.printf("%f", p*q);
Joni
  • 108,737
  • 14
  • 143
  • 193
0

The number 333.6 is not representable exactly as a float, which has up to 6 decimal digits precision. When you tried to print it with too much precision (8 digits) the underlying rounding error was revealed.

double has up to 15 digits precision.

However, as others have pointed out, if you are dealing with financial calculations you should work in BigDecimal.

For reference you can use the IEEE-754 Floating-Point Conversion website to see, for any given decimal number, exactly how it is represented in float and double.

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
-1

The issue here is that floating points are subject to floating point precision errors. You can use double for twice the precision (you will still eventually get errors, but it is more accurate than using float).

E.g.

public static void main(String[] args) {
    int q = 48;
    double p = 6.95;

    System.out.println(q * p);
}

This will give 333.6.

jh314
  • 27,144
  • 16
  • 62
  • 82