同等のfloor $ 1/0
死刑が執行されていることに気づきました。
λ> 1/0
Infinity
とき、これは、これまで私が理解して正常な動作ですが、Infinity
あるfloor
「Dまたはceiling
D」
λ> floor $ 1/0
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
失敗する代わりに、この非常に大きな数が生成されます。どうして?
おそらくもっと重要なのは、別の関数を適用する前に、フィルターを使用せずにこれを障害のない結果と区別するにはどうすればよいですか?
最初の質問はおそらくそれほど重要ではないので、最初に2番目の質問に答えようとします。
数を取得したら、それがから来たものfloor x
であることがわかっている場合、それx
がの有効な表現であったか、2^1024
それとも無限大であったかを知ることはできません。doubleの範囲外のものは無効であり、無限大、負の無限大、NaNなどから生成されたと考えられます。あなたの値が関数の多くの1 /使用して有効であるかどうかを確認するために非常に簡単になります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#
仮数と指数を返すことに注意してください。ウィキペディアによると:
正と負の無限大は次のように表されます。正の無限大の場合はsign = 0、負の無限大の場合は1です。バイアスされた指数=すべての1ビット。分数=すべて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です。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加