Почему использование целочисленных переменных вызывает исключение? - PullRequest
7 голосов
/ 01 августа 2010

Я столкнулся со следующими двумя кодами. Почему он не генерирует исключение для плавающей запятой, где, как в другом случае, он генерирует исключение времени выполнения.

class FloatingPoint
    {
      public static void main(String [] args)
       {
         float a=1000f;
         float b=a/0;
        System.out.println("b=" +b);
       }
    }

ВЫВОД:. Б = бесконечность 1006 *

Если я попытаюсь использовать значения int, это вызовет исключение времени выполнения. Почему это так?

Ответы [ 4 ]

12 голосов
/ 01 августа 2010

Краткий ответ

Интегральные типы ( JLS 4.2.1 ) категорически отличаются от типов с плавающей запятой ( JLS 4.2.3 ). Могут быть сходства в поведении и операциях, но есть также характерные различия, такие, что их смешение может привести ко многим подводным камням.

Разница в поведении при делении на ноль является лишь одним из этих различий. Таким образом, короткий ответ заключается в том, что Java ведет себя так, потому что язык так говорит.


Об интегральных значениях и значениях с плавающей запятой

Значения целочисленных типов являются целыми числами в следующих диапазонах:

  • byte: от -128 до 127 включительно, т. Е. [-27, 27-1]
  • short: от -32768 до 32767 включительно, то есть [-215, 215-1]
  • int: от -2147483648 до 2147483647 включительно, т. Е. [-231, 231-1]
  • long: от -9223372036854775808 до 9223372036854775807 включительно, т.е. [-263, 263-1]
  • char, от '\u0000' до '\uffff' включительно, то есть от 0 до 65535, т.е. [0, 216-1]

Типами с плавающей точкой являются float и double, которые концептуально связаны с 32-битным и 64-битным форматами с одинарной точностью IEEE 754 значения и операции.

Их значения упорядочены следующим образом, от наименьшего к наибольшему:

  • отрицательная бесконечность,
  • отрицательные конечные ненулевые значения,
  • положительный и отрицательный ноль (т.е. 0.0 == -0.0),
  • положительные конечные ненулевые значения и
  • положительная бесконечность.

Кроме того, существуют специальные Not-a-Number (NaN) значения, которые являются неупорядоченными . Это означает, что если один (или оба!) Операнд равен NaN:

  • операторы числового сравнения <, <=, > и >= return false
  • оператор числового равенства == возвращает false
  • оператор числового неравенства != возвращает true

В частности, x != x равно true тогда и только тогда, когда x равно NaN.

Например, double, бесконечности и NaN могут упоминаться как:

Ситуация аналогична float и Float.


Включается, когда могут создаваться исключения

Числовые операции могут выдавать Exception только в следующих случаях:

  1. NullPointerException, если требуется распаковка конверсии null ссылки
  2. ArithmeticException, если правая часть равна нулю для целое число операции деления / остатка
  3. OutOfMemoryError, если требуется преобразование в бокс и недостаточно памяти

Они упорядочены по важности, что является общим источником ловушек. Вообще говоря:

  • Будьте особенно осторожны с типами ящиков, как и все другие ссылочные типы, они могут быть null
  • Будьте особенно осторожны с правой частью целочисленных операций деления / остатка
  • Арифметическое переполнение / недостаточность НЕ вызывает исключение
  • Потеря точности НЕ вызывает исключение
  • Математически неопределенная операция с плавающей запятой НЕ вызывает исключение

На деление на ноль

Для целое число Операция:

  • Операции деления и остатка генерируют ArithmeticException, если правая часть равна нулю

Для с плавающей запятой Операция:

  • Если левый операнд равен NaN или 0, результат равен NaN.
  • Если операция деление , она переполняется, и результатом является бесконечность со знаком
  • Если операция остаток , результат равен NaN

Общее правило для всех операций с плавающей запятой следующее:

  • Операция, которая переполняется, создает бесконечность со знаком.
  • Операция, которая переполняется, производит денормализованнуюзначение или ноль со знаком.
  • Операция, которая не имеет математически определенного результата, дает NaN.
  • Все числовые операции с NaN в качестве операнда дают NaN в результате.

Приложение

По-прежнему существует много вопросов, не охваченных этим уже длинным ответом, но читателям рекомендуется просматривать связанные вопросы и ссылочные материалы.

вопросы

11 голосов
/ 01 августа 2010

Поскольку числа с плавающей точкой имеют представление для "числа", которое вы пытаетесь вычислить.Так что он использует это.Целое число не имеет такого представления.

Java (в основном) следует IEEE754 за поддержку с плавающей запятой, подробнее см. здесь .

2 голосов
/ 01 августа 2010

Это потому, что целочисленная арифметика всегда оборачивает свой результат, за исключением случая (Деление / Остаток по нулю).
В случае с плавающей запятой, когда есть переполнение или недополнение, перенос обнуляется до 0, бесконечности или NaN.
Во время переполнения он дает бесконечность, а во время переполнения - 0.
Опять есть положительные и отрицательные переполнения / недополнения.
Попробуйте:

float a = -1000;
float b = a/0;
System.out.println("b=" +b);

Это дает отрицательный переполнение

выход

б = -Infinity

Аналогичным образом, положительный недостаток приведет к 0, а отрицательный - к -0.
Некоторые операции могут также привести к возврату NaN (не числа) с помощью float / double.
Например:

float a = -1000;
double b = Math.sqrt(a);
System.out.println("b=" +b);

выход

* +1025 * Ь = NaN
1 голос
/ 01 августа 2010

Это стандарт программирования и математики для представления / с нулевыми значениями.У float есть поддержка представления таких значений в JAVA.Тип данных int (integer) не может представлять их в JAVA.

Проверка:

http://en.wikipedia.org/wiki/Division_by_zero

http://www.math.utah.edu/~pa/math/0by0.html

...