Подтвердить что ты не робот

Дистанция на ноль в Хаскелле

Я обнаружил довольно странную несогласованность между поведением 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 правильно приводит к исключению. A NaN может быть приемлемым для /, но почему Infinity? Для такого результата нет математического обоснования. Вы знаете причину этого, пожалуйста?

4b9b3361

Ответ 1

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

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

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

Prelude> 1/(-0)
-Infinity

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

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

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

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

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

Ответ 2

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

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

Ответ 3

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

Пример:

Prelude> 10 ** 10 ** 10
Infinity

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

Ответ 4

Fractional не равен типу Float (или Double).

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