Подтвердить что ты не робот

Как поведение целых типов ведет себя в Java для чисел за пределами целых чисел?

Вот моя программа.

public class Foo
{
    public static void main(String[] args)
    {
        System.out.println((int) 2147483648l);
        System.out.println((int) 2147483648f);
    }
}

Вот результат.

-2147483648
2147483647

Почему нет 2147483648l и 2147483648f типа приведения к одному и тому же целому числу? Можете ли вы объяснить, что здесь происходит, или какую концепцию в Java мне нужно понять, чтобы предсказать вывод подобных типов?

4b9b3361

Ответ 1

Это примеры операции Сужение примитивного преобразования.

В первом примере long - int:

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

Итак, ваш (int) 2147483648l принимает 64 бита long:

00000000 00000000 00000000 00000000 10000000 00000000 00000000 00000000

... и полностью отбрасывая верхние 32 бита:

10000000 00000000 00000000 00000000

... и взятие остальных 32 бит как int. Поскольку самый левый из них теперь является битом знака (long и int хранятся в виде двух дополнений), и поскольку он оказывается установленным в вашем значении 2147483648l, вы получаете отрицательное число. Поскольку никакие другие биты не установлены, в двух дополнениях это означает, что у вас есть самое низкое отрицательное число int может представлять: -2147483648.

Пример float to int следует за более сложным правилом. Соответствующие части для вашей ценности:

... если число с плавающей запятой не является бесконечностью, значение с плавающей запятой округляется до целочисленного значения V, округляя к нулю с использованием режима округления к нулю (IEEE 754) (§4.2.3).

... [if] значение [слишком] (положительное значение большой величины или положительная бесконечность), [тогда] результатом первого шага является наибольшее представимое значение типа int или long.

(Но см. часть спецификации, указанной выше для деталей.)

Так как 2147483648f округляется до 2147483648, а 2147483648 слишком велико, чтобы поместиться в int, вместо этого используется наибольшее значение для int (2147483647).

Итак, в long до int, это бит битва; в float до int, это более математично.


В комментарии вы спросили:

Знаете ли вы, почему оба (short) 32768 и (short) 32768f оцениваются на -32768? Я был последним для оценки до 32767.

Отличный вопрос, и что там, где находится моя "см. часть спецификации, приведенной выше для деталей" выше.:-) (short) 32768f действительно, (short)(int)32768f:

В разделе spec, приведенном выше, в разделе "Сужение преобразования числа с плавающей запятой в интегральный тип T принимает два шага:", говорится:

  • На первом шаге число с плавающей запятой преобразуется либо в long, если T является long, либо в int, если T является byte, short, char, или int...

а затем на втором шаге второй стадии:

  1. * Если T byte, char или short, результат преобразования является результатом сужения преобразования в тип T (п. 5.1.3) результата первого шага.

Итак, на первом этапе 32768f становится 32768 (значение int), а затем, конечно, (short)32768 показывает бит-chopping, который мы видели в long = > int выше, что дает нам a short значение -32768.

Ответ 2

Ницца! Это замечательно видеть, что эффекты дизайнерских решений представлены так, как вы.

2147483648l - это тип long, а правило преобразования long, которое слишком велико для int, - применить правило обертки к типу назначения. (Под капотом значимые биты из типа источника просто отбрасываются.)

2147483648f - это тип float, а правило преобразования float, которое слишком велико для типа назначения, должно максимально использовать для целевого типа. Ссылка Являются ли примитивные приведения типа целочисленного типа "capped" в MAX_INT типа литья?

Хорошая вещь о стандартах заключается в том, что есть так много на выбор.