Первые три выхода из int
и short
легко объяснить:
-2147483648 // your method returns an int, so overflows
2.147483648E9 // Math.pow returns a double, so formatted like this
2147483648 // double casted to a long, 2147483648 inside the possible range for long
32768 // your method returns an int, 32768 is inside the possible range for int
32768.0 // Math.pow returns a double, so formatted like this
32768 // double casted to an int, 32768 is inside the possible range for int
Сложный для объяснения бит - четвертый результат.Не следует ли System.out.println((int)Math.pow(2, 31));
печатать -2147483648?
Хитрость здесь в том, как Java выполняет преобразование из double
в int
.Согласно спецификации, это известно как сужающее примитивное преобразование ( §5.1.3 ):
22 конкретные преобразования на примитивных типах называются сужающими примитивными преобразованиями:
- short to byte или char
- char to byte или short
- int в byte, short или char
- long в byte, short, charили int
- с плавающей запятой в байтах, коротких, char, int или long
- с двойным байтом, короткими, символами, int, long или float
Вот как выполняется преобразование double
в int
(выделено мной):
1.На первом шаге число с плавающей запятой преобразуется либо в long, если T long, либо в int, если T байтовое, короткое, char или int, следующим образом:
- Если число с плавающей запятой равно NaN (§4.2.3), результатом первого шага преобразования будет int или long 0.
- В противном случае, если число с плавающей запятой равноне бесконечность, значение с плавающей запятой округляется до целочисленного значения V с округлением до нуля с использованием режима округления до нуля IEEE 754 (§4.2.3).Тогда есть два случая:
a.Если T длинный, и это целочисленное значение может быть представлено как long, то результатом первого шага будет длинное значение V. b.В противном случае, если это целочисленное значение может быть представлено как int, то результатом первого шага будет значение int V.
В противном случае один из следующих двух случаев долженбыть правдой: a.Значение должно быть слишком маленьким (отрицательное значение большой величины или отрицательная бесконечность), а результатом первого шага является наименьшее представимое значение типа int или long. б.Значение должно быть слишком большим (положительное значение большой величины или положительная бесконечность), и результатом первого шага является наибольшее представимое значение типа int или long.
- На втором шаге:
Если T является int или long, результат преобразования является результатом первого шага.
- Если T является байтом, символом или коротким, результатом преобразования является результат сужающего преобразования в тип T (§5.1.3) результата первого шага.
Первый шаг изменяет значение double на наибольшее представимое значение int
- 2147483647. Вот почему в случае int
печатается 2147483647.В случае short
, второй шаг изменяет значение int
2147483647 на short
, например:
Сужающее преобразование целого числа со знаком в целочисленный тип T просто отбрасываетвсе, кроме n младших битов, где n - количество битов, используемых для представления типа T.
Вот почему short
перелетел, но int
не сделал!