Почему 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?