haskell - real - ¿Por qué el piso infinito no arroja algún error?
real float haskell (1)
La primera pregunta quizás no sea tan importante, así que intentaré responder la segunda pregunta primero.
Una vez que tenga un número, si sabe que proviene del floor x
, no puede saber si x
fue la representación válida de 2^1024
o si fue infinito. Probablemente pueda asumir que cualquier cosa fuera del rango de doble no es válida y se produjo desde el infinito, el infinito negativo, NaN o similares. Sería bastante sencillo verificar si su valor es válido utilizando una / muchas de las funciones en RealFloat
, como isNaN
, isInfinite
, etc.
También podrías usar algo como data Number a = N a | PosInf | NegInf
data Number a = N a | PosInf | NegInf
data Number a = N a | PosInf | NegInf
. Luego escribes:
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"
..
El mejor enfoque se basa principalmente en su caso de uso.
Tal vez sería correcto que floor (1/0)
sea un error. Pero el valor es basura de todos modos. ¿Es mejor lidiar con la basura o un error?
Pero ¿por qué 2^1024
? GHC.Float
un vistazo a la fuente de 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
Tenga en cuenta que decodeFloat_Int#
devuelve la mantisa y el exponente. Según wikipedia :
El infinito positivo y negativo se representan así: signo = 0 para infinito positivo, 1 para infinito negativo. exponente sesgado = todos los 1 bits. fracción = todos los 0 bits.
Para Float
, esto significa una base de 2 ^ 23, ya que hay 23 bits en la base y un exponente de 105 (¿por qué 105? Realmente no tengo idea. Creo que debería ser 255 - 127 = 128, pero Parece ser en realidad 128-23). El valor de floor
es fromIntegral m * (2 ^ n)
o base*(2^exponent) == 2^23 * 2^105 == 2^128
. Para el doble este valor es 1024.
Me encontré con un caso en el que se estaba ejecutando el equivalente al floor $ 1/0
.
λ> 1/0
Infinity
Por lo que yo entiendo, este es un comportamiento normal, pero cuando Infinity
es el floor
''d'' o el ceiling
''d
λ> floor $ 1/0
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
En lugar de fallar, se produce este número muy grande. ¿Por qué?
Quizás más importante, ¿cómo puedo distinguir esto de un resultado no defectuoso sin usar un filtro antes de aplicar otra función?