Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does flooring infinity not throw some error?

I found myself having a case where the equivalent of floor $ 1/0 was being executed.

λ> 1/0
Infinity

This is normal behavior as far as I understand but, when Infinity is floor'd or ceiling'd

λ> floor $ 1/0   
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216

Instead of failing, this very big number is produced. Why?

Maybe more importantly, how can I distinguish this from a non faulty result without using a filter before applying another function?

like image 768
gxtaillon Avatar asked Jun 21 '14 05:06

gxtaillon


People also ask

What happens if you divide by 0 in C?

In languages like C, C++ etc. division by zero invokes undefined behaviour. So according to the language definition, anything can happen.

How do you find the divide by zero error?

Dividing a number by Zero is a mathematical error (not defined) and we can use exception handling to gracefully overcome such operations. If you write a code without using exception handling then the output of division by zero will be shown as infinity which cannot be further processed.

What happens if u divide by 0 in Java?

Dividing by zero is an operation that has no meaning in ordinary arithmetic and is, therefore, undefined.

What does 0 mean in Java?

'0' is the char value of zero. When you write a string, you're writing an array of 'char' datatypes which the compiler translates into ASCII values (which have a corresponding decimal number value).


1 Answers

The first question is perhaps not so important, so I'll try to answer the second question first.

Once you have a number, if you know that it came from floor x, you can't know whether x was the valid representation of 2^1024 or if it was infinity. You can probably assume anything outside of the range of double is invalid and was produced from infinity, negative infinity, NaN or the like. It would be quite simple to check if your value is valid using one/many of the functions in RealFloat, like isNaN, isInfinite, etc.

You could also use something like data Number a = N a | PosInf | NegInf. Then you write:

instance RealFrac a => RealFrac (Number a) where 
  ...
  floor (N n) = floor n
  floor PosInf = error "Floor of positive infinity"
  floor NegInf = error "Floor of negative infinity"
  ..

Which approach is best is based mostly on your use case.

Maybe it would be correct for floor (1/0) to be an error. But the value is garbage anyways. Is it better to deal with garbage or an error?

But why 2^1024? I took a look at the source for GHC.Float:

properFraction (F# x#)
  = case decodeFloat_Int# x# of
    (# m#, n# #) ->
        let m = I# m#
            n = I# n#
        in
        if n >= 0
        then (fromIntegral m * (2 ^ n), 0.0)
        else let i = if m >= 0 then                m `shiftR` negate n
                               else negate (negate m `shiftR` negate n)
                 f = m - (i `shiftL` negate n)
             in (fromIntegral i, encodeFloat (fromIntegral f) n)

floor x     = case properFraction x of
                (n,r) -> if r < 0.0 then n - 1 else n

Note that decodeFloat_Int# returns the mantissa and exponent. According to wikipedia:

Positive and negative infinity are represented thus: sign = 0 for positive infinity, 1 for negative infinity. biased exponent = all 1 bits. fraction = all 0 bits.

For Float, this means a base of 2^23, since there are 23 bits in the base, and an exponent of 105 (why 105? I actually have no idea. I would think it should be 255 - 127 = 128, but it seems to actually be 128 - 23). The value of floor is fromIntegral m * (2 ^ n) or base*(2^exponent) == 2^23 * 2^105 == 2^128. For double this value is 1024.

like image 103
user2407038 Avatar answered Oct 21 '22 12:10

user2407038