2012-02-19 17 views
24

Ho trovato una strana incoerenza tra il comportamento di div e /.Divisione per zero in 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 

sono stato molto sorpreso di notare che la divisione per zero frazionale porta a Infinity, mentre div conduce correttamente un'eccezione. Un NaN potrebbe essere accettabile anche per /, ma perché Infinity? Non c'è giustificazione matematica per un risultato del genere. Conosci la ragione di questo, per favore?

+3

Matematicamente, avere il risultato di '1/0' essere' Infinito' è completamente giustificato. Non è l'unico valore di ritorno giustificabile, ma quello che ha più senso. Notare che si otterrà anche un errore 'divide per zero' se si valuta' 1/0 :: Rational'. –

+5

@DanielFischer: Non lo chiamerei "matematicamente completamente giustificato", in quanto questo tipo di compattazione (con infinito positivo e negativo) distrugge un bel po 'di teoremi che resistono a ℝ, e alcuni di questi sono assunti in molti programmi. – leftaroundabout

+1

Non dovresti assumere cose del genere quando lavori con numeri in virgola mobile. Anche le proprietà di base come l'associatività non sono necessariamente valide. L'uguaglianza non è anche riflessiva per 'NaN's! (Ad esempio '(0/0)/= (0/0)'. –

risposta

41

La ragione per cui div non restituisce Infinity è semplice: non esiste alcuna rappresentazione per infinito nel tipo Integer.

/ rendimenti Infinity perché segue lo standard IEEE 754 poiché il tipo predefinito Fractional (che descrive galleggianti rappresentazioni numeriche punto) è Double. Anche altre lingue con numeri in virgola mobile (ad es. JavaScript) presentano questo comportamento.

Per rendere matematici rabbrividire ancora di più, si ottiene un risultato diverso se si divide da negativo 0, nonostante il fatto che -0 == 0 per i galleggianti:

Prelude> 1/(-0) 
-Infinity 

Questo è anche il comportamento dallo standard.

Se si utilizza un tipo diverso frazionale come Rational, si otterrà il comportamento che si aspettano:

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

Per coincidenza, se vi state chiedendo sul perché Integer e Double sono i tipi in questione quando il funzionamento effettivo non li fa riferimento, dai un'occhiata a come Haskell gestisce i tipi predefiniti (in particolare i tipi numerici) nello report.

La versione breve è che se si dispone di un tipo ambiguo dalla classe Num, Haskell tenterà prima Integer e poi Double per quel tipo. È possibile modificare questo con una dichiarazione default (Type1, Type2...) o disattivarlo con una dichiarazione default() a livello di modulo.

+0

Dove posso conoscere l'istruzione 'default'? Non l'ho mai vista prima. – amindfv

+1

La sezione del rapporto che ho collegato a copiarlo vicino Alla fine, penso che sia menzionato anche nella Gentile Introduzione a Haskell, ma non sono sicuro che ci sia molto di più rispetto a quello che ho trattato qui. A meno che non abiliti alcune estensioni, riguarda solo i tipi numerici e si comporta come ho spiegato .) –

+0

Preludio> 1/(- (0) Errore programma: {primDivDouble 1.0 0.0} –

6

Spero che questo aiuta:

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

Grazie ... sì sembra proprio un limite messo in quel modo. –

3

frazionale è non uguale Float (o doppio) tipo.

Frazione di 1/n dove n va a 0 così lim (n → 0) 1/n = + ∞, lim (n → 0) -1/n = -∞ e questo ha senso.

+0

Penso che un vincolo 'Fractional' venga impostato di default a' Double', che è un tipo a virgola mobile. Leggi la sezione del rapporto a cui mi sono collegato. –

+0

Corretto, @TikhonJelvis, a meno che non ci sia una dichiarazione di default che dice altrimenti, un tipo ambiguo con un vincolo 'Fractional' è impostato su' Double'. –

5

Potrebbe non essere così per una ragione matematica. Infinity viene usato a volte come "sin bin": tutto ciò che non funziona nel nostro sistema in modo pulito, lo inserisce lì.

Esempio:

Prelude> 10 ** 10 ** 10 
Infinity 

... non è assolutamente giustificata matematicamente!

+1

Non hai ancora incontrato un finitista rigido! :) – Ingo

+0

@Ingo Hard core come in zero, uno, infinito? –

+0

@Daniel Intendo le persone che sostengono che un numero come 10^100 non ha senso in quanto non ci sono tanti oggetti nell'universo. Ma forse preferirebbero 10^10^10 = NaN – Ingo

Problemi correlati