2012-02-19 22 views
24

Encontré una inconsistencia bastante extraña entre el comportamiento de div y /.División por cero en Haskell

*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 quedé bastante sorprendido de notar que la división por cero fraccionada conduce a Infinity, mientras que div conduce correctamente a una excepción. A NaN también podría ser aceptable para /, pero ¿por qué Infinity? No hay justificación matemática para tal resultado. ¿Conoces la razón de esto, por favor?

+3

Matemáticamente, tener el resultado de '1/0' ser' Infinito' está completamente justificado. No es el único valor de retorno justificable, sino el que tiene más sentido. Tenga en cuenta que también obtendrá un error de 'divide por cero' si evalúa '1/0 :: Rational'. –

+5

@DanielFischer: No lo llamaría "justificado matemáticamente por completo", ya que este tipo de compactación (con infinito positivo y negativo) destruye bastantes teoremas que se mantienen ℝ, y algunos de ellos se asumen en muchos programas. – leftaroundabout

+1

No debe suponer cosas así al trabajar con números de coma flotante. Incluso las propiedades básicas como la asociatividad no necesariamente se mantienen. La igualdad tampoco es reflexiva para 'NaN's! (Por ejemplo '(0/0)/= (0/0)'. –

Respuesta

41

La razón de que no vuelve divInfinity es simple - no hay representación para el infinito en el tipo Integer.

/ rendimientos Infinity porque sigue el estándar IEEE 754 (que describe flotantes representaciones numéricas punto) desde el tipo predeterminado Fractional es Double. Otros lenguajes con números de coma flotante (por ejemplo, JavaScript) también exhiben este comportamiento.

Para hacer los matemáticos se encogen aún más, se obtiene un resultado diferente si se divide por negativo 0, a pesar del hecho de que -0 == 0 de flotadores:

Prelude> 1/(-0) 
-Infinity 

Este es también el comportamiento de la norma.

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

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

Casualmente, si se está preguntando acerca de por qué Integer y Double son los tipos en cuestión cuando su funcionamiento real no hace referencia a ellos, eche un vistazo a cómo Haskell maneja los tipos por defecto (especialmente los tipos numéricos) en el report.

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

+0

¿Dónde puedo obtener información acerca de la instrucción 'default'? No lo he visto antes. – amindfv

+1

La sección del informe que he vinculado lo cubre cerca de Al final, creo que también se menciona en la Introducción suave a Haskell. Sin embargo, no estoy seguro de que haya mucho más que lo que cubrí aquí. (A menos que habilite algunas extensiones, solo se refiere a los tipos numéricos y se comporta como lo expliqué .) –

+0

Preludio> 1/(- 0) Error de programa: {primDivDouble 1.0 0.0} –

6

espero que esto ayude:

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

Gracias ... sí, parece un límite puesto de esa manera. –

3

fraccionada es no igual al flotador (o doble) tipo.

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.

+0

Creo que una restricción 'Fraccional' se predetermina a 'Doble', que es un tipo de coma flotante. Lea la sección del informe al que me he vinculado. –

+0

Correcto, @TikhonJelvis, a menos que exista una declaración predeterminada que diga lo contrario, un tipo ambiguo con una restricción 'Fraccional' está predeterminado en' Doble'. –

5

Puede que no sea así por una razón matemática. Infinity se usa a veces como un "recipiente de pecado": todo lo que no funciona en nuestro sistema limpiamente, lo pone allí.

Ejemplo:

Prelude> 10 ** 10 ** 10 
Infinity 

... definitivamente no es matemáticamente justificado!

+1

¡Aún no conoces a un experto en hard core! :) – Ingo

+0

@Ingo Núcleo duro como en cero, uno, infinito? –

+0

@Daniel Me refiero a las personas que sostienen que un número como 10^100 no tiene sentido ya que no hay tantos objetos en el universo. Pero quizás prefieran 10^10^10 = NaN – Ingo

Cuestiones relacionadas