如何在不假设固定位数的情况下读取足够的数据来反序列化 Int 类型的种子?
How do I read enough data to deserialize a seed of type Int without assuming a fixed number of bits?
我们得到 mkStdGen
has type Int
→ StdGen
和 Int
定义为
A fixed-precision integer type with at least the range [-2^29 .. 2^29-1]
. The exact range for a given implementation can be determined by using minBound
and maxBound
from the Bounded
class.
换句话说,Int
的宽度没有固定的上限。
Expert Beginner 可能会想,'但是 GHC 在我的机器上使用 31 位 Int
- 对 Simon Peyton Jones 来说足够好应该对任何人都足够好!'并且非常自我满足写
generator :: IO StdGen
generator = do
withBinaryFile "/dev/urandom" ReadMode $ \h -> do
let nbytes = 4
buf = take nbytes $ repeat (0::Word8)
toInt ws =
let [a,b,c,d] = (map fromIntegral ws) :: [Word32] in
fromIntegral $ (shiftL (clearBit a 7) 24) .|.
(shiftL b 16) .|.
(shiftL c 8) .|. d
withArray buf $ \p -> do
nread <- hGetBuf h p nbytes
when (nread /= nbytes) $ error "failed read"
bytes <- peekArray nbytes p
return $ mkStdGen (toInt bytes)
我们的英雄没有想到要检查 64 位 GHC:
Prelude> maxBound :: Int
9223372036854775807
Prelude> 2^63
9223372036854775808
或其他 Haskell 其 Int
具有最小 29 位。
我们如何实现 generator
以避免浪费或溢出种子位?
FiniteBits
class 得到了您的支持。
Data.Bits> finiteBitSize (0 :: Int)
64
我们得到 mkStdGen
has type Int
→ StdGen
和 Int
定义为
A fixed-precision integer type with at least the range
[-2^29 .. 2^29-1]
. The exact range for a given implementation can be determined by usingminBound
andmaxBound
from theBounded
class.
换句话说,Int
的宽度没有固定的上限。
Expert Beginner 可能会想,'但是 GHC 在我的机器上使用 31 位 Int
- 对 Simon Peyton Jones 来说足够好应该对任何人都足够好!'并且非常自我满足写
generator :: IO StdGen
generator = do
withBinaryFile "/dev/urandom" ReadMode $ \h -> do
let nbytes = 4
buf = take nbytes $ repeat (0::Word8)
toInt ws =
let [a,b,c,d] = (map fromIntegral ws) :: [Word32] in
fromIntegral $ (shiftL (clearBit a 7) 24) .|.
(shiftL b 16) .|.
(shiftL c 8) .|. d
withArray buf $ \p -> do
nread <- hGetBuf h p nbytes
when (nread /= nbytes) $ error "failed read"
bytes <- peekArray nbytes p
return $ mkStdGen (toInt bytes)
我们的英雄没有想到要检查 64 位 GHC:
Prelude> maxBound :: Int
9223372036854775807
Prelude> 2^63
9223372036854775808
或其他 Haskell 其 Int
具有最小 29 位。
我们如何实现 generator
以避免浪费或溢出种子位?
FiniteBits
class 得到了您的支持。
Data.Bits> finiteBitSize (0 :: Int)
64