Правила, регулирующие сужение двойного до целого

Обратите внимание, что я НЕ ищу код для приведения или сужения двойного к int.

Согласно JLS - $ 5.1.3. Сужение примитивного преобразования

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

Итак, когда я пытаюсь сузить 260 (двоичное представление как 100000100) к байту, то результат равен 4, потому что младшие 8 бит 00000100 который является десятичным 4 ИЛИ длинное значение 4294967296L (двоичное представление 100000000000000000000000000000000) к байту, то результатом будет 0.

Теперь, почему я хочу знать правило для сужения правила от двойного до целого, байта и т. Д., Это когда я сужаю double значение 4294967296.0 тогда результат 2147483647 но когда я сужаю длинный 4294967296L значение, то результат 0,

Я понял длинное сужение до int, байтов и т. Д. (Отбрасывает все, кроме n младших битов), но я хочу знать, что происходит под капотами в случае двойного сужения.

3 ответа

Решение

Я понял длинное сужение до int, байтов и т. Д. (Отбрасывает все, кроме n младших битов), но я хочу знать, что происходит под капотами в случае двойного сужения.

... Я хочу понять, почему и как часть.

  1. JLS ( JLS 5.1.3) определяет, каков результат. Упрощенная версия (для int) является:

    • NaN становится равным нулю
    • Inf становится "max-int" или "min-int"
    • иначе:
      • округлить до нуля, чтобы получить математическое целое число
      • если округленное число слишком велико для int, результат становится "min-int" или "max-int"
  2. "Как" зависит от реализации. Для примеров того, как это может быть реализовано, посмотрите на исходный код Hotspot (версия OpenJDK) или заставьте JIT-компилятор вывести некоторый нативный код для просмотра. (Я полагаю, что карты нативного кода используют единственную инструкцию для фактического преобразования.... но я не проверял.)

  3. "Почему" непостижимо... если вы не можете спросить одного из оригинальных разработчиков Java / авторов спецификаций. Правдоподобное объяснение представляет собой сочетание:

    • это легко понять
    • это согласуется с C / C++,
    • это может быть эффективно реализовано на общих аппаратных платформах, и
    • это лучше, чем (гипотетические) альтернативы, которые рассматривали дизайнеры.

    (Например, создание исключения для NaN, Inf вне допустимого диапазона будет несовместимо с другими примитивными преобразованиями и может быть более дорогим для реализации.)

Когда вы начинаете с двойного значения 4294967296.0, оно больше наибольшего длинного значения, равного 2147483647, поэтому применяется следующее правило (со страницы, на которую вы ссылались): значение должно быть слишком большим (положительное значение большой величины или положительная бесконечность)), и результатом первого шага будет наибольшее представимое значение типа int или long, и вы получите 0x7FFFFFF = 2147483647

Но когда вы пытаетесь преобразовать 4294967296L = 0x100000000, вы начинаете с целочисленного типа, поэтому правило таково: сужающее преобразование целого числа со знаком в целочисленный тип T просто отбрасывает все, кроме n младших битов, поэтому, если n меньше 32 (8 байт) вы просто получите 0.

Результатом является Integer.MAX_VALUE при преобразовании двойного числа в целое, и значение превышает диапазон целого числа. Integer.MAX_VALUE - 2^31 - 1.

Другие вопросы по тегам