为什么地板无穷大不会引起一些错误?

gxt*_*lon 18 floating-point haskell infinity floor

我发现自己有一个案例,相当于floor $ 1/0正在执行.

?> 1/0
Infinity
Run Code Online (Sandbox Code Playgroud)

这是正常的行为,据我理解,但,当Infinityfloor"d或ceiling" d

?> floor $ 1/0   
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
Run Code Online (Sandbox Code Playgroud)

而不是失败,而是产生了这么大的数字.为什么?

也许更重要的是,在应用其他功能之前,如何在不使用过滤器的情况下将其与非故障结果区分开来?

use*_*038 9

第一个问题也许并不那么重要,所以我将首先尝试回答第二个问题.

一旦你有一个数字,如果你知道它来自floor x,你就不知道它是否x是无效的有效表示2^1024.你可以假设任何超出double范围之外的东西是无效的,并且是由无穷大,负无穷大,NaN等产生的.这将是很简单的检查,如果你的价值使用一个/许多的功能是有效的RealFloat,比如isNaN,isInfinite等等.

你也可以使用类似的东西data Number a = N a | PosInf | NegInf.然后你写:

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"
  ..
Run Code Online (Sandbox Code Playgroud)

哪种方法最好主要基于您的用例.

也许floor (1/0)成为一个错误是正确的.但无论如何,价值都是垃圾.处理垃圾或错误更好吗?

但为什么2^1024呢?我看了一下这个来源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
Run Code Online (Sandbox Code Playgroud)

请注意,decodeFloat_Int#返回尾数和指数.根据维基百科:

因此,正和负无穷大表示:正无穷大符号= 0,负无穷大符号为1.偏置指数=全1位.分数=全0位.

因为Float,这意味着2 ^ 23的基数,因为基数中有23位,指数为105(为什么105?我实际上不知道.我认为它应该是255 - 127 = 128,但似乎实际上是128 - 23).值的值floorfromIntegral m * (2 ^ n)base*(2^exponent) == 2^23 * 2^105 == 2^128.对于double,此值为1024.