-2

Here is what i tried:

public class LongToDoubleTest{
    public static void main(String... args) {
        System.out.println(Long.MAX_VALUE);
        System.out.println(Long.MAX_VALUE/2);
        System.out.println(Math.floor(Long.MAX_VALUE/2));
        System.out.println(new Double(Math.floor(Long.MAX_VALUE/2)).longValue());
    }
}

Here is the output:

9223372036854775807
4611686018427387903
4.6116860184273879E18
4611686018427387904

I was initially trying to figure out, is it possible to keep half of the Long.MAX_VALUE in double without losing data, So I had a test with all those lines, except the last one. So it appeared that i'm right and last 3 was missing. Then, just to clarify it, I added last line. And not 3 appeared but 4. So my question is, from where those 4 appeared and why it's 4 and not 3. Because 4 is actually an incorrect value here. P.S. I'm very poor in knowledge of IEEE 754, so maybe behaviour I found is absolutely correct, but 4 is obviously a wrong value here.

dhblah
  • 9,751
  • 12
  • 56
  • 92

2 Answers2

7

You need to understand that not every long can be exactly represented as a double - after all, there are 2568 long values, and at most that many double values (although lots of those are reserved for "not a number" values etc). Given that there are also double values which clearly aren't long values (e.g. 0.5 - any non-integer, for a start) that means there can't possibly be a double value for every long value.

That means if you start with a long value that can't be represented, convert it to a double and then back to a long, it's entirely reasonable to get back a different number.

The absolute difference between adjacent double values increases as the magnitude of the numbers gets larger. So when the numbers are very small, the difference between two numbers is really tiny (very very small indeed) - but when the numbers get bigger - e.g. above the range of int - the gap between numbers becomes greater... greater even than 1. So adjacent double values near Long.MAX_VALUE can be quite a distance apart. That means several long values will map to the same nearest double.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • So `4` I got in the end was absolutely unpredicted? It could be with equal probability `9` or `7`? – dhblah Jul 29 '13 at 18:02
  • @dhblah: Well no - for any given `long`, there will be exactly one `double` that it should be rounded to. It's predictable if you look at the exact bit patterns involved - but not easily predictable to the naked eye. – Jon Skeet Jul 29 '13 at 18:03
  • I mean, that `4` doesn't mean that rounding went wrong it's just because of bit pattern? – dhblah Jul 29 '13 at 18:04
  • @dhblah: Indeed. There's nothing *wrong* here - it's just a natural consequence of there not being an exact `double` representation of every `long` value. – Jon Skeet Jul 29 '13 at 18:11
  • @dhblah If you look at the IEEE 754 floating-point format, you can see that the `Long` that cannot be represented exactly as a `double` is instead converted to a multiple of a power of two, so the last decimal digit of the number obtained through the conversion will **never** be 9 or 7. – Pascal Cuoq Jul 29 '13 at 18:20
  • 1
    On the positive side, every integer between -9.007199254740992E15 and 9.007199254740992E15 is exactly representable in double. – Patricia Shanahan Jul 29 '13 at 22:26
  • @PatriciaShanahan: Surely that's on both the positive *and* negative side. On the positive side, it's just 1 to 9.007199254740992E15 ;) – Jon Skeet Jul 29 '13 at 22:27
2

The arithmetic here is completely predictable.

The Java double format uses one bit for sign and eleven bits for exponent. That leaves 52 bits to encode the significand (the fraction portion of a floating-point number).

For normal numbers, the significand has a leading 1 bit, followed by a binary point, followed by the 52 bits of the encoding.

When Long.MAX_VALUE/2, 4611686018427387903, is converted to double, it must be rounded to fit in these bits. 4611686018427387903 is 0x3fffffffffffffff. There are 62 significant bits there (two leading zeroes that are insignificant, then 62 bits). Since not all 62 bits fit in the 53 bits available, we must round them. The last nine bits, which we must eliminate by rounding, are 1111111112. We must either round them down to zero (producing 0x3ffffffffffffe00) or up to 10000000002 (which carries into the next higher bit and produces 0x4000000000000000). The latter change (adding 1) is smaller than the former change (subtracting 1111111112). We want a smaller error, so we choose the latter and round up. Thus, we round 0x3fffffffffffffff up to 0x4000000000000000. This is 262, which is 4611686018427387904.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312