Почему деление на ноль с номерами с плавающей запятой (или двойной точностью) не вызывает java.lang.ArithmeticException: / на ноль в Java

Следующий оператор бросает java.lang.ArithmeticException: / by zero как очевидный.

 System.out.println(0/0); 

потому что буква 0 считается int literal и деление на ноль не допускается в целочисленной арифметике.

Следующий случай, однако, не вызывает никаких исключений, таких как java.lang.ArithmeticException: / by zero .

 int a = 0; double b = 6.199; System.out.println((b/a)); 

Он отображает Infinity .

Следующий оператор производит NaN (Not a Number) без исключения.

 System.out.println(0D/0); //or 0.0/0, or 0.0/0.0 or 0/0.0 - floating point arithmetic. 

В этом случае оба операнда считаются двойными.


Аналогичным образом, следующие утверждения не вызывают никаких исключений.

 double div1 = 0D/0; //or 0D/0D double div2 = 0/0D; //or 0D/0D System.out.printf("div1 = %s : div2 = %s%n", div1, div2); System.out.printf("div1 == div2 : %b%n", div1 == div2); System.out.printf("div1 == div1 : %b%n", div1 == div1); System.out.printf("div2 == div2 : %b%n", div2 == div2); System.out.printf("Double.NaN == Double.NaN : %b%n", Double.NaN == Double.NaN); System.out.printf("Float.NaN == Float.NaN : %b%n", Float.NaN == Float.NaN); 

Они производят следующий выход.

 div1 = NaN : div2 = NaN div1 == div2 : false div1 == div1 : false div2 == div2 : false Double.NaN == Double.NaN : false Float.NaN == Float.NaN : false 

Они все возвращают false. Почему эта операция (деление на ноль) разрешена с номерами с плавающей запятой или двойной точностью?


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

Короче говоря, это то, как это указано в стандарте IEEE-754, на котором основаны операции Floating-Point на Java.

Почему не деление на ноль (или переполнение или недостаточное) останавливает программу или вызывает ошибку? Почему стандарт по номерам включает «not-a-number» (NaN)?

Модель 754 поощряет надежные программы. Он предназначен не только для численных аналитиков, но и для пользователей электронных таблиц, систем баз данных или даже кофейников. Правила распространения для NaNs и бесконечностей допускают неосуществимые исключения для обращения в нуль. Аналогичным образом, постепенное недополнение поддерживает свойства ошибки в диапазоне точности.

Когда в исключительных ситуациях требуется внимание, они могут быть проверены немедленно через ловушки или в удобное время через флаги состояния. Ловушки могут использоваться для остановки программы, но неустранимые ситуации крайне редки. Простота остановки программы не является вариантом для встроенных систем или сетевых агентов. Чаще всего ловушки регистрируют диагностическую информацию или заменяют действительные результаты.

Флаги предлагают как предсказуемый stream управления, так и скорость. Их использование требует, чтобы программист знал об исключительных условиях, но липкость флагов позволяет программистам откладывать обработку исключительных условий до тех пор, пока это не будет необходимо.

Это так, потому что именно так определил IEEE 754.

Разделение по плавающей точке 0.0 дает NaN или +/- Inf, в зависимости от того, является ли числитель 0 или нет.

Разделение на целое число 0 не распространяется на IEEE 754 и генерирует исключение – другого способа указания ошибки нет, поскольку int не может представлять NaN или Inf .

Генерирование исключения аналогично (программному) INT генерируемому делением на ноль на микропроцессорах x86.

Бесконечность не предел

 class DoubleDivision { public static void main(String[] args) { System.out.println(5.0/0.0); } } 

Вышеупомянутый код и fragmentы, которые вы упомянули, дают infinity .

Почему Java использует Double s для представления десятичных знаков. Двоичный не может полностью представить число, он может представлять только приближение, и поэтому ни одна из них не может быть двойной.

Представьте себе число, невероятно близкое к нулю. Если вы знаете исчисление, представьте себе предел в ноль. Переменная будет приближаться к нулю до некоторого воображаемого крошечного расстояния, но никогда точно не будет равна. Вы можете себе это представить, верно? Ну, предположим, что для числа требуется так много точности для представления Java, он отказывается и называет его 0.0 потому что у него нет хорошей альтернативы. Вот что здесь происходит. Любое регулярное число, деленное на супер близкое число к нулю, в основном, бесконечно . Попробуйте: 5 / (10^-100) .

Также обратитесь к разделу: Специальные значения с плавающей запятой в Math Errors для получения дополнительной информации 🙂

Связанный вопрос: почему 1/0 дает ошибку, но 1.0 / 0/0 дает inf

UPDATE: INT не имеет бесконечности и значения NaN в наборе, тогда как float имеет бесконечность и значение NaN . (Согласно стандартам IEEE 754, которые соответствуют java)

Когда есть деление на ноль, компьютер не может создать представление результата в виде числа. Компьютер должен сигнализировать, что результат не является числом.

Для значений с плавающей запятой он может создавать специальное значение нечётного числа, потому что существуют 32-битные (для float ) и 64-битные (для double ) битовых шаблонов, которые не представляют число, и поэтому могут быть интерпретированы как не-число ( NaN ).

Для целочисленных значений, использующих общую схему двойного дополнения (как требуется Java), все 32-разрядные (для int ) и 64-разрядные (для long ) битовые шаблоны представляют собой число. Поэтому компьютер не может сообщить о проблеме с помощью дозорного устройства. Он должен каким-то образом сообщать о проблеме «вне диапазона». Выбрасывание исключения – это метод вне диапазона, выбранный для Java.

Java следует стандарту IEEE 754, который определяет значения для возврата по умолчанию в случае деления на ноль. http://en.wikipedia.org/wiki/IEEE_754#Exception_handling

Разделение на ноль (операция с конечными операндами дает точный бесконечный результат, например, 1/0 или log (0)) (по умолчанию возвращает ± бесконечность).

 import java.util.Scanner; public class Division { public static void main(String[] args) { int a, b; float result; Scanner input = new Scanner(System.in); System.out.println("Enter value for a : "); a = input.nextInt(); System.out.println("Enter value for b : "); b = input.nextInt(); try { /* here we used "if clause" because result will be in float note: Here result is in float, so JVM Cant Catch Exception. if we Try to Divide with Zero with Float Values It gives Output as Divided by Zero is Infinity */ if (b != 0) { result = (float) a / b; System.out.println("Result of " + a + " divided by " + b + " is : " + result); } else // here result will be in integer so Jvm can easily Catch The Exception { result = a / b; } } catch (ArithmeticException e) { System.out.println("Sorry Division By Zero Is Not Possible"); } } } /* Ouput : Enter value for a :2 Enter value for b : 7 Result of 2 divided by 7 is : 0.2857143 */ /* Ouput : Enter value for a : 16 Enter value for b : 0 Sorry Division By Zero Is Not Possible */ 
Interesting Posts
Давайте будем гением компьютера.