Изменение значения при конвертации длинных в двойные и обратно - PullRequest
0 голосов
/ 11 февраля 2011

с учетом следующего кода:

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

гарантированно ли следующее выражение истинно?

l == (long) d

Я должен подумать, что нет, потому что по мере того, как числа увеличиваются, разрывы между двумя двойными числами растут больше 1, и поэтому обратное преобразование дает другое длинное значение. В случае, если преобразование не принимает значение, превышающее значение long, это также может произойти раньше.

Есть ли однозначный ответ на этот вопрос?

Ответы [ 3 ]

5 голосов
/ 11 февраля 2011

Нет, абсолютно нет.Существует множество значений long, которые не могут быть точно представлены double.Фактически, это имеет , чтобы иметь место, учитывая, что оба типа представлены в 64 битах, и, очевидно, существует множество значений double, которые не могут быть представлены в long (например, 0,5)

Простой пример (Java и затем 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);
    }
}

Я наблюдал что-то действительно странное , когда делал это, хотя ... в C #, long.MaxValue "работал"с точки зрения печати False ... тогда как в Java мне пришлось использовать Long.MAX_VALUE - 1.Я предполагаю, что это происходит из-за некоторых встроенных и 80-битных операций с плавающей точкой в ​​некоторых случаях ... но это все еще странно:)

1 голос
/ 02 мая 2014

Мой код начинается с 0 и увеличивается на 100 000 000. Было обнаружено, что наименьшее число, не прошедшее тест, составило 2 305 843 009 300 000 000 (19 цифр). Таким образом, любой положительный лонг менее 2 305 843 009 200 000 000 представлен точно в два раза. В частности, 18-значные длинные значения также представлены в точности двойными числами.

Кстати, причина, по которой меня заинтересовал этот вопрос, заключается в том, что я задавался вопросом, могу ли я использовать double для представления меток времени (в миллисекундах). Поскольку текущие временные метки имеют порядок 13 цифр (и для них потребуется довольно много времени, чтобы добраться до 18 цифр), я сделаю это.

1 голос
/ 11 февраля 2011

Вы можете проверить это, поскольку существует конечное число длинных значений.

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");
  }
}

Не нужно много итераций, чтобы доказать это;

l = -9223372036854775805
d = -9,223372036854776E18
(длинный) d = -9223372036854775808

...