Почему (длинный) 9223372036854665200d дает мне 9223372036854665216? - PullRequest
9 голосов
/ 18 октября 2011

Я знаю о странных вещах с ошибками точности, но не могу понять,

Почему (long)9223372036854665200d дает мне 9223372036854665216?

Ответы [ 5 ]

34 голосов
/ 18 октября 2011

9223372036854665200d является константой типа double. Однако 9223372036854665200 не подходит для double без потери точности. A double имеет только 52 бита мантиссы, в то время как для рассматриваемого числа требуется 63 бита для точного представления.

Ближайшим double к 9223372036854665200d является число, чья мантисса равна 1.1111111111111111111111111111111111111111111110010100 в двоичном, а показатель степени равен 63 (десятичный). Этот номер является не чем иным, как 9223372036854665216 (назовите его U).

Если мы уменьшим мантиссу на одну ступень до 1.1...0011, мы получим 9223372036854664192 (назовите это L).

Исходное число находится между L и U и намного ближе к U, чем L

Наконец, если вы думаете, что это усечение мантиссы должно привести к числу, оканчивающемуся на кучу нулей, вы правы. Только это происходит в двоичном, а не в десятичном виде: U в base-16 равно 0x7ffffffffffe5000 и L равно 0x7ffffffffffe4c00.

16 голосов
/ 18 октября 2011

Потому что у двойников не так много точности.Почему ты делаешь такую ​​странную вещь?Измените d на l.

6 голосов
/ 18 октября 2011

Doubles имеют точность 52-53 бита, тогда как long имеет 64-битную точность (только для целых чисел).Потеря точности в двойном выражении используется для представления показателя степени, что позволяет double представлять большие / меньшие числа, чем long банка.

Ваш номер длиной 19 цифр, тогда как двойная банкахранить только приблизительно 16 цифр (десятичных) целочисленных данных.Таким образом, окончательное число заканчивается округлением.

Ссылка: Double - Википедия

5 голосов
/ 18 октября 2011

Потому что двойные имеют ограниченную точность . Ваша константа имеет более значимые цифры, чем может отследить двойная, поэтому она теряет их.

3 голосов
/ 18 октября 2011

Вы предполагаете, что ограниченная точность означает, что она представлена ​​в десятичном виде, поэтому ограничена 15 или 16 цифрами. На самом деле он представлен в двоичном формате и ограничен 53 битами точности. double принимает ближайшее представимое значение.

double d = 9223372036854665200d;
System.out.println(d +" is actually\n" + new BigDecimal(d)+" so when cast to (long) is\n"+(long) d);

печать

9.2233720368546652E18 is actually 
9223372036854665216 so when cast to (long) is 
9223372036854665216
...