Это потому, что 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
.