Почему 1/0 дает ошибку, а 1/0.0 возвращает "Inf"?

Мне просто интересно об этом:

При оценке 1/0 в Java возникает следующее исключение:

Исключение в потоке "main" java.lang.ArithmeticException: / на ноль в Foo.main(Foo.java:3)

Но 1/0.0 оценивается в Infinity,

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

Почему это происходит?

4 ответа

Решение

Это потому, что целые числа не имеют значений +/-Inf, NaN и не допускают деление на 0, в то время как числа с плавающей точкой имеют эти специальные значения.

1/0 - это деление на два типа int, которое выдает исключение, потому что вы не можете делить на целое число ноль. Однако 0.0 является литералом типа double, и Java будет использовать деление с плавающей точкой. Спецификация IEEE с плавающей точкой имеет специальные значения для деления на ноль (среди прочего), одним из которых является double.Infinity.

Если вас интересуют подробности, у спецификации с плавающей запятой (которая часто загадочна) есть страница в Википедии: http://en.wikipedia.org/wiki/IEEE_754-2008, и ее полный текст также можно прочитать онлайн: http://ieeexplore.ieee.org/xpl/mostRecentIssue.jsp?punumber=4610933.

1/0 - это целочисленное деление, 1/0.0 - это деление с плавающей запятой - числа с плавающей запятой могут представлять недопустимые значения, а целые числа - нет.

IEEE определил определенные стандарты для чисел с плавающей запятой, которые включают определения для "не числа" и положительной и отрицательной бесконечности. Это не относится к целым числам.

См. http://steve.hollasch.net/cgindex/coding/ieeefloat.html

Причина этих особых случаев в основном в ошибках округления. Числа с плавающей точкой часто всегда усекаются, потому что они никогда не являются точными. Целые, с другой стороны, всегда точны.

fetestexcept а также feenableexcept

Стоит отметить, что базовое оборудование ЦП может обнаруживать конкретный случай 0.0 / 0.0, а также:

  • установить некоторые биты флага, которые можно запросить с помощью ANSI C fetestexcept(FE_ALL_EXCEPT) == FE_INVALID
  • вызвать исключение, если это было включено с feenableexcept(FE_INVALID) расширение glibc

Однако я не смог найти, предоставляет ли Java эту функциональность.

Вот минимальный исполняемый пример C: В чем разница между тихим NaN и сигнальным NaN?

Другие вопросы по тегам