Почему Java не генерирует исключение при делении на 0,0?

У меня есть код для вычисления процентной разницы между двумя номерами - (oldNum - newNum) / oldNum * 100; - где оба числа double s. Я ожидал, что мне придется добавить какую-то проверку/обработку исключений, если oldNum равно 0. Однако, когда я выполнил тестовый прогон со значениями 0.0 для oldNum и newNum, выполнение продолжалось, как будто ничего не произошло, и ошибка не была выбрана. Выполнение этого кода с помощью int, безусловно, вызовет арифметическое исключение с разбивкой на нуль. Почему Java игнорирует его, когда дело доходит до double s?

Ответ 1

Результат деления на ноль, математически говоря, undefined, который может быть выражен с помощью float/double (как NaN - не число), это не так, однако, неправильно в любом фундаментальном смысле.

Как целое число должно содержать определенное числовое значение, при обработке с ним необходимо делить на ноль.

Ответ 2

Java float и double, как и любой другой язык (и практически любой аппаратный модуль FP), реализуйте IEEE 754 для математики с плавающей запятой, которая требует деления на ноль, чтобы вернуть особое значение "бесконечности". Выброс исключения фактически нарушит этот стандарт.

Целочисленная арифметика (реализована как представление двух дополнений Java и большинства других языков и аппаратных средств) отличается и не имеет специальных значений бесконечности или NaN, поэтому бросание исключений - полезное поведение там.

Ответ 3

То, как хранится double, сильно отличается от int. См. http://firstclassthoughts.co.uk/java/traps/java_double_traps.html для более подробного объяснения того, как Java обрабатывает двойные вычисления. Вы также должны прочитать цифры чисел плавающей запятой, в частности концепцию Not a Number (NaN).

Если вам интересно узнать больше о представлении с плавающей запятой, я бы посоветовал прочитать этот документ (формат Word, извините). Он вникает в двоичное представление чисел, что может быть полезно для вашего понимания.

Ответ 4

Хотя разработчики Java знают о двойном примитивном типе и классе Double, делая арифметику с плавающей запятой, они не уделяют достаточного внимания Double.INFINITY, NaN, -0.0 и другим правилам, которые определяют арифметические вычисления с их участием.

Простой ответ на этот вопрос заключается в том, что он не будет бросать ArithmeticException и возвращать Double.INFINITY. Также обратите внимание, что сравнение x == Double.NaN всегда оценивается как false, даже если x сам является NaN.

Чтобы проверить, является ли x NaN, следует использовать вызов метода Double.isNaN(x), чтобы проверить, является ли заданный номер NaN или нет. Это очень близко к NULL в SQL.

Это может быть полезно для вас.

Ответ 5

При делении на ноль (0 или 0.00)

  • Если вы разделите double на 0, JVM покажет Бесконечность.

    public static void main(String [] args){ double a=10.00; System.out.println(a/0); }

    Консоль: Infinity

  • Если вы разделите int на 0, тогда JVM выкинет Арифметическое исключение.

    public static void main(String [] args){ int a=10; System.out.println(a/0); }

    Консоль: Exception in thread "main" java.lang.ArithmeticException: / by zero

  • Но если мы разделим int на 0.0, то JVM покажет бесконечность:

    public static void main(String [] args){ int a=10; System.out.println(a/0.0); }

    Консоль: Infinity

Это связано с тем, что JVM автоматически вводит cast int в double, поэтому мы получаем бесконечность вместо ArithmeticException.