Ответ 1
Первый вопрос, возможно, не так важен, поэтому я постараюсь сначала ответить на второй вопрос.
Как только у вас есть номер, если вы знаете, что он пришел из floor x
, вы не можете знать, было ли x
допустимым представлением 2^1024
или если оно было бесконечным. Вероятно, вы можете предположить, что все, что находится вне диапазона двойника, является недопустимым и было создано из бесконечности, отрицательной бесконечности, 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"
..
Какой подход лучше всего основан в основном на вашем случае использования.
Возможно, было бы правильным для 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
Обратите внимание, что decodeFloat_Int#
возвращает мантиссы и экспонента. Согласно wikipedia:
Положительная и отрицательная бесконечность представлены таким образом: sign = 0 для положительная бесконечность, 1 для отрицательной бесконечности. смещенный показатель = все 1 биты. fraction = все 0 бит.
Для Float
это означает базу из 2 ^ 23, так как в базе 23 бита, а показатель 105 (почему 105? Я действительно не знаю. Я бы подумал, что это должно быть 255 - 127 = 128, но, на самом деле, оно составляет 128 - 23). Значение floor
равно fromIntegral m * (2 ^ n)
или base*(2^exponent) == 2^23 * 2^105 == 2^128
. Для double это значение равно 1024.