2010-03-04 3 views
60

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

+4

Хороший вопрос - несогласованность между целым и двойным поведением добавляет путаницу и хлопот. –

+2

Возможный дубликат [Почему деление на ноль с номерами с плавающей запятой (или двойной точностью) не вызывает java.lang.ArithmeticException:/на ноль в Java] (http://stackoverflow.com/questions/12954193/why-does- – Raedwald

+2

@ Raedwald - учитывая, что этот вопрос был отправлен за 2 1/2 года до того, с которым вы связались, я бы сказал, что вопрос - это (возможно) дубликат этого :) – froadie

ответ

42

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

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

+6

Точно. Это определено в Java Language Spec здесь: http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2.3 –

+1

Я попытался вывести результат, и это значение NaN. Означает ли это, что ints не может удерживать NaN? – froadie

+1

, но это случай «0.0/0.0», который является NaN. –

4

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

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

101

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

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

+3

Правильный ответ на этот вопрос должен быть таким. Мне нужно было знать, почему 'float' и' double' не вызывают исключения. Благодарю. –

+1

Это должен быть обозначенный правильный ответ.Ответ, который в настоящее время отмечен как правильный, не отвечает на вопрос, и не дает понять, что Java соответствует IEEE 754. – Necrototem

3

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

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

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

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

1

при делении на ноль (0 или 0,00)

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

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

    консоли: Infinity

  2. Если разделить ИНТ на 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

  3. Но если мы разделим ИНТ на 0.0, то JVM будет показывать бесконечность:

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

    консоли: Infinity

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

Смежные вопросы