Ответ 1
Причина, по которой это имеет значение, состоит в том, что номер научной нотации 3.1558E+10
является литералом double
, тогда как литерал 31558000000L
является, конечно, литералом long
.
Это делает разницу в операторе +=
.
Выражение составного присваивания формы E1 op = E2 эквивалентно E1 = (T) ((E1) op (E2)), где T - тип E1, за исключением того, что E1 оценивается только один раз.
В принципе, long + = long дает длинный, но long + = double также дает длинный.
При добавлении double
начальное значение cumSeconds
расширяется до double
, а затем происходит добавление. Результат претерпевает сужение примитивного преобразования до long
.
Сужение преобразования числа с плавающей запятой интегральному типу T выполняется двумя шагами:
- На первом этапе число с плавающей запятой преобразуется либо в long, если T long
(надрез)
В противном случае должен выполняться один из следующих двух случаев:
Значение должно быть слишком маленьким (отрицательное значение большой величины или отрицательной бесконечности), а результат первого шага - наименьшее представимое значение типа int или long.
Значение должно быть слишком большим (положительное значение большой величины или положительной бесконечности), а результатом первого шага является наибольшее представимое значение типа int или long.
(смелый акцент мой)
Результат в конечном итоге слишком большой, чтобы быть представленным в long
, поэтому результат сужается до Long.MAX_VALUE
, а цикл while
заканчивается.
Однако, когда вы используете литерал long
, вы постоянно добавляете четное значение к четному значению, которое в конечном итоге будет переполняться. Это не устанавливает значение Long.MAX_VALUE
, которое является нечетным, поэтому цикл бесконечен.