Почему деление целого числа на ноль и приведение его к типу float приводит к бесконечности? - PullRequest
3 голосов
/ 08 сентября 2011

Я уже искал разные вопросы по этой теме, но не получил четкого представления. Проверьте этот код:

class Test{
    public static void main(String[] s){
        int a=5;
        float b=(float)a/0;
        System.out.print(b);
    }
}

вывод Infinity. Но я не понимаю, что a это int, и a/0 должен выдать исключение. Так как же это может показать вывод Infinity?

Ответы [ 8 ]

8 голосов
/ 08 сентября 2011

Причина в том, что

(float)a/0;

интерпретируется как

((float)a)/0;

а не

(float)(a/0);

так что вы фактически конвертируете a в float перед выполнением деления, а не целочисленного деления, а затем конвертируете результат.

Надеюсь, это поможет!

4 голосов
/ 08 сентября 2011

Вы не делите целое число на ноль.Вы делите float на ноль, потому что ваше выражение эквивалентно:

float b=((float)a)/0;

Если вы заставляете деление происходить только с целыми числами, как в следующем примере, ожидаемоеArithmeticException будет брошено .

float b=(float)(a/0);
2 голосов
/ 08 сентября 2011

Все вычисления с плавающей запятой соответствуют спецификации IEEE 754. В частности, там три специальных значения с плавающей точкой для обозначения переполнений и ошибок:

• Положительная бесконечность • Отрицательная бесконечность • NaN (не число)

Например, результатом деления положительного числа на 0 является положительная бесконечность. вычисления 0/0 или квадратный корень из отрицательного числа дает NaN.

см. Также

ВНИМАНИЕ: числа с плавающей точкой не подходят для финансовых расчет, при котором ошибки округления не могут быть допущены. Например, команда System.out.println (2.0 - 1.1) печатает 0.8999999999999999, а не 0.9, как вы ожидаете. такие Ошибки округления вызваны тем, что числа с плавающей точкой представлены в двоичной системе счисления. Там нет точного двоичного представление дроби 1/10, так как нет точного представление дроби 1/3 в десятичной системе. Если тебе надо точные численные вычисления без ошибок округления, используйте Класс BigDecimal, который будет представлен позже в этой главе.

из ядра Java Том 1, глава 3

1 голос
/ 08 сентября 2011

Поскольку вы разыгрываете a в число с плавающей точкой, а затем делитесь на ноль. Поплавки имеют +/- бесконечность.

http://www.velocityreviews.com/forums/t137207-division-by-zero-float-vs-int.html

1 голос
/ 08 сентября 2011

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

Приведение к числу с плавающей запятой a генерирует автоматическое приведение 0всплыть

1 голос
/ 08 сентября 2011

Это потому, что Java не допускает деление на ноль с int с, а делает со значениями с плавающей точкой.

1 голос
/ 08 сентября 2011

a - это int, за исключением того, что вы разыгрываете его на float во время деления.Обратите внимание, что приведение имеет более высокий приоритет, чем деление - для ясности в скобках это будет:

float b = ((float) a)/0;

Так что, пока a является целым числом, вы выполняете деление с плавающей точкой.

0 голосов
/ 08 сентября 2011

Двоичный / оператор выполняет деление, производя частное от своих операндов. Левый операнд - это дивиденд, а правый операнд - делитель.

Целочисленное деление округляет до 0. То есть частное, полученное для операндов n и d, которые являются целыми числами после двоичного числового преобразования (§5.6.2), является целочисленным значением q, величина которого максимально возможна при удовлетворении | d · д || п |; более того, q положительно, когда | n || d | и n и d имеют один и тот же знак, но q отрицательно, когда | n || d | и n и d имеют противоположные знаки. Существует один особый случай, который не удовлетворяет этому правилу: если дивиденд является отрицательным целым числом наибольшей возможной величины для его типа, а делитель равен -1, то происходит переполнение целого числа, и результат равен дивиденду. Несмотря на переполнение, в этом случае не возникает исключений. С другой стороны, если значение делителя в целочисленном делении равно 0, возникает исключение ArithmeticException.

Результат деления с плавающей запятой определяется спецификацией арифметики IEEE:

If either operand is NaN, the result is NaN.
If the result is not NaN, the sign of the result is positive if both operands have the same sign, negative if the operands have different signs.
Division of an infinity by an infinity results in NaN.
Division of an infinity by a finite value results in a signed infinity. The sign is determined by the rule stated above.
Division of a finite value by an infinity results in a signed zero. The sign is determined by the rule stated above.
Division of a zero by a zero results in NaN; division of zero by any other finite value results in a signed zero. The sign is determined by the rule stated above.
Division of a nonzero finite value by a zero results in a signed infinity. The sign is determined by the rule stated above.
In the remaining cases, where neither an infinity nor NaN is involved, the exact mathematical quotient is computed. A floating-point value set is then chosen:
    If the division expression is FP-strict (§15.4):
        If the type of the division expression is float, then the float value set must be chosen.
        If the type of the division expression is double, then the double value set must be chosen. 
    If the division expression is not FP-strict:
        If the type of the division expression is float, then either the float value set or the float-extended-exponent value set may be chosen, at the whim of the implementation.
        If the type of the division expression is double, then either the double value set or the double-extended-exponent value set may be chosen, at the whim of the implementation. 

Next, a value must be chosen from the chosen value set to represent the quotient. If the magnitude of the quotient is too large to represent, we say the operation overflows; the result is then an infinity of appropriate sign. Otherwise, the quotient is rounded to the nearest value in the chosen value set using IEEE 754 round-to-nearest mode. The Java programming language requires support of gradual underflow as defined by IEEE 754 (§4.2.4). 

Несмотря на то, что может произойти переполнение, недополнение, деление на ноль или потеря информации, оценка оператора деления с плавающей запятой / никогда не выдает исключение времени выполнения.

Это можно проверить по адресу: http://docs.oracle.com/javase/specs/jls/se5.0/html/expressions.html#15.17.2

...