2016-07-25 6 views
8

Я провел следующий фрагмент в VS2015 C# в интерактивном режиме и получил очень странное поведение.Почему этот метод возвращает double.PositiveInfinity не DivideByZeroException?

> double divide(double a, double b) 
. { 
.  try 
.  { 
.   return a/b; 
.  } 
.  catch (DivideByZeroException exception) 
.  { 
.   throw new ArgumentException("Argument b must be non zero.", exception); 
.  } 
. }  
> divide(3,0) 
Infinity  
> 3/0 
(1,1): error CS0020: Division by constant zero 
> var b = 0; 
> 3/b 
Attempted to divide by zero. 
> 

Почему метод возвращал бесконечность, в то время как 3/0 забросил ошибку, а 3/b сбросил форматированную ошибку? Могу ли я заставить деление выбросить ошибку, а не возвращать бесконечность?

Если я переформатировать метод

double divide(double a, double b) 
{ 
    if (b == 0) 
    { 
     throw new ArgumentException("Argument b must be non zero.", new DivideByZeroException()); 
    } 
    return a/b; 
} 

бы новый DivideByZeroException содержит ту же информацию и структуру, что поймано исключение будет?

ответ

14

Это потому, что вы используете System.Double.

Как указано MSDN DivideByZeroException выбрасывается только для интегральных типов и десятичных чисел.

Это потому, что трудно определить «так называемый» ноль для двойного значения.

PositiveInfinity также является результат деления на нуль с положительными дивидендов, и результатами NegativeInfinity от деления на ноль с отрицательными дивидендами. (источник: MSDN again)

DivideByZeroException не подходит для типов с плавающей точкой. Примечание. Вы можете получить NaN, хотя при попытке деления на ноль с дивидендом нулевой.

1

Почему метод возвращал бесконечность, в то время как 3/0 забросил ошибку, и 3/ b забросил форматированную ошибку?

Потому что в первом случае 0 не является целым числом, является двойным. Пока во втором есть целое число. То, что вы должны понимать здесь, состоит в том, что double является числом с плавающей запятой. Таким образом, он не имеет точного значения, как целое число. С другой стороны, целое число может быть представлено компьютером со 100% точностью.

Here вы можете найти очень хорошую статью о числах с плавающей запятой.

0

Int в Java является дополнением 2. Целое число с двумя дополнениями не имеет битов, доступных для хранения специальных значений, таких как Infinity или NaN, поэтому, поскольку результат не представляется в желаемом типе, необходимо исключить исключение. Числа с плавающей запятой не имеют этой проблемы (для Infinity имеется бит-шаблон), поэтому исключение не требуется.

+4

Этот вопрос не о java – pquest

+0

My bad! Хотя это относится и к C#. – codemonger

+1

@codemonger Математически говоря, N/0 не равно бесконечности. Более разумно исключать исключение, чем для любого возвращаемого значения, даже учитывая, что числа с плавающей запятой поддерживают значение +/- Infinity. NaN будет более уместным, чем бесконечность. –

1

Как указано выше, это связано с использованием двойника в качестве делителя. Вы можете это доказать, используя пример переменных, но используя double вместо var.

> double a = 3; 
> double b = 0; 
> a/b 
∞ 
+0

Спасибо, что указали, что я забыл, что использовал var. Указание 0 как двойного литерала, оцененного как бесконечность. –