1
import java.text.*;

public class TryStuffOut {
    public static void main(String[] args) {
       double n=12323233.445;
       DecimalFormat x = new DecimalFormat("#.##");
       System.out.println(x.format(n));
    }
}

why does this round the decimal part down to .44 and when i switch the variable n to double n=12323233.415; it rounds up to .42 . Why? and does the # in front of the deicmal matter to how many digits I have because it still seems to print out the entire number even thought I only have 1 pound sign.

Thanks

Zabuzard
  • 25,064
  • 8
  • 58
  • 82
Tony
  • 387
  • 1
  • 2
  • 14
  • @Zabuzard what do you mean it was never ..5 to begin with? i stated it in my variable so shouldn't it be what i state? – Tony Dec 02 '20 at 17:36
  • 2
    @Tony you can't exactly represent all base 10 decimals in base 2. You can only represent numbers that are approximately the same. – Andy Turner Dec 02 '20 at 17:37
  • 2
    @Tony you're not actually using `12323233.445`, you're using `12323233.445000000298`, which is the closest representable number. – Andy Turner Dec 02 '20 at 17:39
  • @AndyTurner ah so whole numbers are represented equally while deicmals will be changed due to the precision thing right? – Tony Dec 02 '20 at 17:41
  • @AndyTurner even then shouldn't it round up because that number that represents what I stated is greater than the round off at 5 – Tony Dec 02 '20 at 17:42
  • 2
    @Tony only some whole numbers can be represented exactly. Once they get too big (I think it's greater than 2^53 for a double), not all whole numbers can be represented either. – Andy Turner Dec 02 '20 at 17:42
  • 1
    Try this: float x = 0.1f; float y = x + x + x + x + x; y = y + x + x + x + x + x; /* 10 x 0.1 */ System.out.println( y ); // => 1.0000001 Even a "simple" number like 0.1 cannot be represented _exactly_ in binary. Like 1/3 cannot be expressed exactly in decimal. – gsl Dec 02 '20 at 17:43
  • By default, rounding mode of DecimalFormat is RoundingMode.HALF_EVEN. All you have to do to get rounding you expect is: decimalFormat.setRoundingMode(RoundingMode.HALF_UP) – Alex Rmcf Dec 02 '20 at 17:48
  • @gsl i see, so decimals basically are not exact and rounding will always cause this discrepency, so theres nothing i can do then – Tony Dec 02 '20 at 17:48
  • @AlexRmcf can you explain what the half even and half up is? – Tony Dec 02 '20 at 17:49
  • 1
    HALF_EVEN prefers rounding to the nearest even number when it's exactly halfway between two numbers – Alex Rmcf Dec 02 '20 at 17:51
  • @AlexRmcf when i set this in my code ` decimalFormat.setRoundingMode(RoundingMode.HALF_UP);` it says the arguments are not defined – Tony Dec 02 '20 at 17:55
  • Please share the full error message and possible the full code example. – Zabuzard Dec 02 '20 at 19:02
  • The posted question states “why does this round the decimal part down to .44”, however, executing the code rounds up to .45, producing “12323233.45”. – Eric Postpischil Dec 03 '20 at 11:27
  • @EricPostpischil You are right, I have adjusted the answers. I trusted OPs observation but turns out its exactly the opposite. The first value is rounded up and the second is rounded down, as originally expected (also edited the duplicates). – Zabuzard Dec 03 '20 at 12:46

1 Answers1

4

Explanation

Due to limited floating point precision your double values are not actually what you wanted to have.

In fact, the values are instead:

12323233.445 -> 12323233.445000000298
12323233.415 -> 12323233.4149999991059

The rounding has to work with that, hence it rounds the first value up and the second value down.

Note that your observation is incorrect and it is exactly the opposite. You claimed that the first would be rounded down while second value is rounded up. But executing it yields the opposite behavior. And that behavior is explained due to above.

Floating point numbers are implemented according to IEE 754 and this specifies exactly how they work internally.


Representation

Now, the thing is that those numbers can not be represented. The specification says that it should then use the closest number that can be represented instead. And that is exactly what is happening here.

You can inspect this further and play with it here:

Zabuzard
  • 25,064
  • 8
  • 58
  • 82
  • Hey thanks for the answer, you said those numbers are represented by the other numbers that you stated, but when I use the decimal format shouldn't it round up for the .445 still? and the .415 round down because of the numbers you stated? – Tony Dec 02 '20 at 17:53
  • Your observation is incorrect. Executing the code leads to the exact opposite behavior. I have edited the answer. – Zabuzard Dec 03 '20 at 12:48