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