Почему следующие операторы дают разные результаты в Java? - PullRequest
1 голос
/ 07 апреля 2020

Для некоторых значений x (x имеет тип long),

 x %= (1e9+7);

и

 x %= 1_000_000_007;

дают разные ответы. Любая идея, почему это может быть?

Кроме того, этот формат подчеркивания (1_000_000_007) распространен среди языков? Есть ли у него преимущества, кроме улучшенной читабельности?

1 Ответ

1 голос
/ 07 апреля 2020

Это потому, что 1e9 является литералом double, и не каждое значение long может быть точно представлено как double, поэтому происходит потеря точности из-за неявного преобразования из long в double.

В соответствии с языковой спецификацией , x %= d эквивалентно x = (long) (x % d), когда x является переменной типа long и d имеет тип double. Остальная операция также выполняет двоичную цифру c Prommotion для операндов, которая преобразует x в тип double.

, поскольку double имеет двойную точность IEEE 754 число с плавающей точкой , оно имеет 53 бита точности для мантиссы, что недостаточно для представления всех 64 битов точности, которые могут потребоваться для значения long. Другими словами, double и long используют 64 бита, но существует много значений double, которые не являются значениями long, поэтому также должно быть много значений long, которые не являются значениями double. Таким образом, неявное преобразование из long в double может привести к потере точности для значений, больших 2 53 или меньших -2 53 .

Кстати, из-за оставшейся операции ошибка из-за потери точности может составлять до 10 9 + 7. Для входного значения 9_223_372_036_563_603_804L ошибка составляет, например, 999_999_659.

...