开发者

Value change when converting a long to a double and back

given the following code:

long l = 1234567890123;
double d = (double) l;

is the following expression guaranteed to be true?

l == (long) d

I should think no, because as numbers get larger, the gaps between two doubles grow beyond 1 and therefore the conversion back yields a different long value. In case the conversion does not take the value that's 开发者_开发百科greater than the long value, this might also happen earlier.

Is there a definitive answer to that?


Nope, absolutely not. There are plenty of long values which aren't exactly representable by double. In fact, that has to be the case, given that both types are represented in 64 bits, and there are obviously plenty of double values which aren't representable in long (e.g. 0.5)

Simple example (Java and then C#):

// Java
class Test {
    public static void main(String[] args) {
        long x = Long.MAX_VALUE - 1;
        double d = x;
        long y = (long) d;
        System.out.println(x == y);
    }
}

// C#
using System;

class Test
{
    static void Main()
    {
        long x = long.MaxValue;
        double d = x;
        long y = (long) d;
        Console.WriteLine(x == y);
    }
}

I observed something really strange when doing this though... in C#, long.MaxValue "worked" in terms of printing False... whereas in Java, I had to use Long.MAX_VALUE - 1. My guess is that this is due to some inlining and 80-bit floating point operations in some cases... but it's still odd :)


You can test this as there are a finite number of long values.

for (long l = Long.MIN_VALUE; l<Long.MAX_VALUE; l++)
{
  double d = (double) l;
  if (l == (long)d)
  {
    System.out.println("long " + l + " fails test");
  }
}

Doesn't take many iterations to prove that;

l = -9223372036854775805
d = -9.223372036854776E18
(long)d = -9223372036854775808


My code started with 0 and incremented by 100,000,000. The smallest number that failed the test was found to be 2,305,843,009,300,000,000 (19 digits). So, any positive long less than 2,305,843,009,200,000,000 is representable exactly by doubles. In particular, 18-digit longs are also representable exactly by doubles.

By the way, the reason I was interested in this question is that I wondered if I can use doubles to represent timestamps (in milliseconds). Since current timestamps are on the order of 13 digits (and it will take for them rather long time to get to 18 digits), I'll do that.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜