Подтвердить что ты не робот

Почему бесконечность напольных покрытий не вызывает какой-либо ошибки?

Я обнаружил, что я имею случай, когда выполняется выполнение floor $ 1/0.

λ> 1/0
Infinity

Это нормальное поведение, насколько я понимаю, но когда Infinity есть floor 'd или ceiling' d

λ> floor $ 1/0   
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216

Вместо того, чтобы терпеть неудачу, это очень большое количество создается. Почему?

Может быть, что более важно, как я могу отличить это от не ошибочного результата без использования фильтра перед применением другой функции?

4b9b3361

Ответ 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.