Деление на ноль в Haskell

я обнаружил довольно странное несоответствие между поведением div и /.

*ghci> :t 1 `div` 0
1 `div` 0 :: Integral a => a
*ghci> :t 1 / 0
1 / 0 :: Fractional a => a
*ghci> 1 / 0
Infinity
*ghci> 1 `div` 0
*** Exception: divide by zero

Я был очень удивлен, заметив, что дробное деление на ноль приводит к Infinity, тогда как div правильно приводит к исключение. А NaN может быть приемлемым для /, но почему Infinity? Для такого результата нет математического обоснования. Вы знаете причину этого, пожалуйста?

4 ответов


причина div не возвращает Infinity просто-нет представления для бесконечности в Integer тип.

/ возвращает Infinity потому что он следует стандарту IEEE 754 (который описывает представления чисел с плавающей запятой), так как по умолчанию Fractional тип Double. Другие языки с числами с плавающей запятой (например, JavaScript) также демонстрируют такое поведение.

чтобы заставить математиков съежиться еще больше, вы получаете другой результат если разделить на отрицательный 0, несмотря на то, что -0 == 0 для поплавков:

Prelude> 1/(-0)
-Infinity

это также поведение от стандарта.

если вы используете другой частичный типа Rational, вы получите поведение, которое вы ожидаете:

Prelude> 1 / (0 :: Rational)
*** Exception: Ratio.%: zero denominator

по совпадению, если вам интересно, почему Integer и Double являются ли типы, о которых идет речь, когда ваша фактическая операция не ссылается на них, посмотрите, как Haskell обрабатывает типы по умолчанию (особенно числовые типы) в отчет.

короткая версия заключается в том, что если у вас есть неоднозначный тип от Num класс, Хаскелл сначала попробовать Integer а то Double для этого типа. Вы можете изменить это с помощью default (Type1, Type2...) заявление или выключить его с помощью default () оператор на уровне модуля.


Я надеюсь, это поможет:

Prelude> 1/0
Infinity
Prelude> -1/0
-Infinity
Prelude> 0/0
NaN

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

пример:

Prelude> 10 ** 10 ** 10
Infinity

... определенно не математически оправдано!


частичная не равно типу Float (или Double).

дробь 1/n, где n переходит в 0, поэтому lim(n→0) 1/n = +∞, lim (n→0) -1/n= -∞, и это имеет смысл.