math haskell division divide-by-zero

math - División por cero en Haskell



division divide-by-zero (4)

Encontré una inconsistencia bastante extraña entre el comportamiento de div y / .

*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

Me sorprendió bastante notar que la división fraccionada por cero conduce al Infinity , mientras que div conduce correctamente a una excepción. Un NaN podría ser aceptable también para / , pero ¿por qué Infinity ? No hay justificación matemática para tal resultado. ¿Sabes la razón de esto, por favor?


Espero que esto ayude:

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


Fraccional no es igual al tipo Flotante (o Doble).

Fracción de 1 / n donde n va a 0, entonces lim (n → 0) 1 / n = + ∞, lim (n → 0) -1 / n = -∞ y eso tiene sentido.


La razón por la que div no devuelve Infinity es simple: no hay representación para infinito en el tipo Integer .

/ devuelve Infinity porque sigue el estándar IEEE 754 (que describe las representaciones de número de punto flotante) ya que el tipo Fractional predeterminado es Double . Otros idiomas con números de punto flotante (por ejemplo, JavaScript) también exhiben este comportamiento.

Para hacer que los matemáticos se hundan aún más, obtienes un resultado diferente si divides entre 0 negativo , a pesar del hecho de que -0 == 0 para flotadores:

Prelude> 1/(-0) -Infinity

Este es también el comportamiento de la norma.

Si usa un tipo fraccional diferente como Rational , obtendrá el comportamiento que espera:

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

Casualmente, si se pregunta por qué Integer y Double son los tipos en cuestión cuando su operación real no hace referencia a ellos, observe cómo Haskell maneja los tipos predeterminados (especialmente los tipos numéricos) en el report .

La versión corta es que si tiene un tipo ambiguo de la clase Num , Haskell probará primero con Integer y luego con Double para ese tipo. Puede cambiar esto con una declaración default (Type1, Type2...) o desactivarla con una instrucción default () en el nivel del módulo.


Puede que no sea así por una razón matemática. Infinity se usa a veces como un "sin bin": todo lo que no funciona de manera limpia en nuestro sistema, póngalo ahí.

Ejemplo:

Prelude> 10 ** 10 ** 10 Infinity

... definitivamente no está justificado matemáticamente!