Riccardo T.
Riccardo T.

Reputation: 8937

Division by zero in Haskell

I found a quite strange inconsistency between the behaviour of div and /.

*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

I was quite surprised to notice that the fractional division by zero leads to Infinity, whereas div correctly leads to an exception. A NaN could be acceptable too for /, but why Infinity? There is no mathematical justification for such a result. Do you know the reason for this, please?

Upvotes: 24

Views: 8963

Answers (4)

Tikhon Jelvis
Tikhon Jelvis

Reputation: 68152

The reason that div does not return Infinity is simple--there is no representation for infinity in the Integer type.

/ returns Infinity because it follows the IEEE 754 standard (which describes floating point number representations) since the default Fractional type is Double. Other languages with floating point numbers (e.g. JavaScript) also exhibit this behavior.

To make mathematicians cringe even more, you get a different result if you divide by negative 0, despite the fact that -0 == 0 for floats:

Prelude> 1/(-0)
-Infinity

This is also behavior from the standard.

If you use a different fractional type like Rational, you will get the behavior you expect:

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

Coincidentally, if you're wondering about why Integer and Double are the types in question when your actual operation does not reference them, take a look at how Haskell handles defaulting types (especially numeric types) in the report.

The short version is that if you have an ambiguous type from the Num class, Haskell will first try Integer and then Double for that type. You can change this with a default (Type1, Type2...) statement or turn it off with a default () statement at the module level.

Upvotes: 44

amindfv
amindfv

Reputation: 8448

It may not be that way for a mathematical reason. Infinity is used sometimes as a "sin bin": everything that doesn't work in our system cleanly, put it in there.

Example:

Prelude> 10 ** 10 ** 10
Infinity

... is definitely not mathematically justified!

Upvotes: 5

David Unric
David Unric

Reputation: 7719

Fractional is not equal to Float (or Double) type.

Fraction of 1/n where n goes to 0 so lim(n→0) 1/n = +∞, lim(n→0) -1/n = -∞ and that makes sense.

Upvotes: 3

9000
9000

Reputation: 40894

I hope this helps:

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

Upvotes: 6

Related Questions