Кастинг Java-типа - float (и long) до int

Я пытаюсь понять кастинг типов в Java. Я прочитал, что long преобразуется в int, используя приведенные по модулю диапазоны int, а float преобразуется в int, удаляя дробную часть. Я попробовал следующий код.

class test
{
    public static void main(String arf[])
    {
        System.out.println((int)2147483648.0);
        System.out.println((int)2147483648L);
    }
}

... где 2147483647 - максимальное значение int.

Вывод:

2147483647
-2147483648

Когда float преобразуется в int, его дробная часть удаляется. Итак, (int)2147483648.0 также должен быть равен -2147483648.

Может кто-нибудь объяснить мне, почему 2147483648.0 передается в 2147483647?

Ответ 1

2147483648.0 на самом деле 2 31 тогда как максимальное значение для int равно 2 31 -1. Таким образом, это значение с плавающей запятой буквально одно значение слишком высоко, чтобы соответствовать.

Причина, по которой он будет усекать его до наивысшего значения int, описана в спецификации языка как сужение преобразования.. p >

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

    • Если число с плавающей запятой NaN (п. 4.2.3), результатом первого шага преобразования является int или long 0.

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

    • Если T длинно, и это целочисленное значение может быть представлено как длинное, то результатом первого шага является длинное значение V.

    • В противном случае, если это целочисленное значение может быть представлено как int, то результатом первого шага является значение int V.

Соответствующая часть здесь состоит в том, что значение будет округлено к нулю. Пока значение (или длинное) с плавающей запятой превышает Integer.MAX_VALUE, приведение к int приведет к его наивысшему значению. То же самое верно для значения, которое меньше, чем Integer.MIN_VALUE.

Что-то любопытное случается, если вы используете (int)-214783649L; он вдруг станет 214783647! Почему это происходит, также объясняется в JLS, мой упор:

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

Длительное представление этого значения в двоичном формате с каналом, обозначающим 32-битное прерывание, выглядит следующим образом:

1111 1111 1111 1111 1111 1111 1111 1111 | 0111 1111 1111 1111 1111 1111 1111 1111

Когда происходит преобразование, первые 32 бита отбрасываются, оставляя вас с максимально возможным int.

Обратное истинно с положительным длинным - более высокие 32 бита содержат все 1s, которые отбрасываются при преобразовании.

Полная структура приведена ниже, при этом труба снова обозначает 32-битную метку:

1111 1111 1111 1111 1111 1111 1111 1111 | 1000 0000 0000 0000 0000 0000 0000 0000

Ответ 2

Независимо от того, какое большее значение (чем int max value) вы указываете как значение float, оно сокращает (соответствует) до int max, которое равно 2147483647

 System.out.println((int)2147483699.0); //2147483647
 System.out.println((int)3147483699.0); //2147483647

Изменить:

Диапазон длинной в java -9,223,372,036,854,775,808 and 9,223,372,036,854,775,807 (inclusive). где -2,147,483,648 and 2,147,483,647 (inclusive).

Итак, если ваше значение long больше/меньше значений, указанных для int, преобразование никогда не бывает точным.

Ответ 3

Компилятор - это smartass. Если вы внимательно наблюдаете за байтовым кодом, вы увидите, что компилятор заменяет значение float на Integer.MAX_VALUE.

Итак, как говорит Суреш, любое значение float выше 2147483647.0 заменяется на 2147483647.

код:

public static void main(String arf[]) {
        int i = (int) 2147483649121.0f;
        System.out.println(i);
        System.out.println((int) 2147483648L);
    }

Байт-код:

public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: ldc           #16                 // HERE : int 2147483647
         2: istore_1      
         3: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;
         6: iload_1       
         7: invokevirtual #23                 // Method java/io/PrintStream.println:(I)V
        10: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;
        13: ldc           #29                 // int -2147483648
        15: invokevirtual #23                 // Method java/io/PrintStream.println:(I)V
        18: return        

Ответ 4

Любое целое число больше 2147483647 вызывает переполнение. Любое задание или литье в этих случаях создает отрицательный максимум int -

look (int) 2147483699L) также производит -2147483647

System.out.println((int)2147483699L);