Почему целочисленное деление на ноль 1/0 дает ошибку, а плавающая точка 1/0.0 возвращает "Inf"?

Мне просто интересно:

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

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

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

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

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

Ответ 1

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

Ответ 2

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

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

Ответ 3

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

Ответ 4

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

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

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

Ответ 5

fetestexcept и feenableexcept

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

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

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

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