【问题标题】:Haskell `randoms` function not behaving well with my libraryHaskell `randoms` 函数在我的库中表现不佳
【发布时间】:2017-05-26 05:23:03
【问题描述】:

我正在尝试编写一个用于加密安全随机数的 Haskell 库。代码如下:

module URandom (URandom, initialize) where

import qualified Data.ByteString.Lazy as B
import System.Random
import Data.Word

newtype URandom = URandom [Word8]

instance RandomGen URandom where
  next (URandom (x : xs)) = (fromIntegral x, URandom xs)
  split (URandom l) = (URandom (evens l), URandom (odds l))
    where evens (x : _ : xs) = x : evens xs
          odds (_ : x : xs) = x : odds xs
  genRange _ = (fromIntegral (minBound :: Word8), fromIntegral (maxBound :: Word8))

initialize :: IO URandom
initialize = URandom . B.unpack <$> B.readFile "/dev/urandom"

不幸的是,它的行为不像我想要的那样。特别是表演

take 10 . randoms <$> initialize

产量(类似于)

[-4611651379516519433,-4611644973572935887,-31514321567846,9223361179177989878,-4611732094835278236,9223327886739677537,4611709625714976418,37194416358963,4611669560113361421,-4611645373004878170,-9223329383535098640,4611675323959360258,-27021785867556,9223330964083681227,4611705212636167666]

在我未经训练的眼睛看来,这并不是很随意。里面有很多 46... 和 92...。

可能出了什么问题?为什么这不能产生分布良好的数字?值得注意的是,即使我将Word8s 连接在一起形成Ints,分布并没有改善,我认为不值得在此处包含该代码。

编辑:这里有一些未正确分发的证据。我写了一个叫做 histogram 的函数:

histogram :: ∀ t . (Integral t, Bounded t)
          => [t] -> Int -> S.Seq Int
histogram [] buckets = S.replicate buckets 0
histogram (x : xs) buckets = S.adjust (+ 1) (whichBucket x) (histogram xs buckets)
  where whichBucket x = fromIntegral $ ((fromIntegral x * fromIntegral buckets) :: Integer) `div` fromIntegral (maxBound :: t)

当我跑步时

g <- initialize
histogram (take 1000000 $ randoms g :: [Word64]) 16

我回来了

fromList [128510,0,0,121294,129020,0,0,122090,127873,0,0,120919,128637,0,0,121657]

有些桶完全是空的!

【问题讨论】:

  • @Programman 我无法重现您的直方图结果,对我来说它给出了[62398,62151,62517,62490,62331,62213,62646,62719,62571,62189,62777,62734,62355,62782,62312,62815],这看起来非常合理。你在什么操作系统上试试这个?
  • 你看过来自 urandom 的原始数字吗?
  • 好吧,根据您的假设,randomIvalInteger 中似乎存在错误。可能值得使用该函数来查看它是否确实存在错误。
  • 升级到 1.1,实现了更好的算法。
  • @Li-yaoXia -- 如果您可以将其发布为答案,那就太好了,也许可以参考或引用 ChangeLog 中关于使用更好算法的内容。它很可能对其他人有帮助,否则会迷失在 cmets 的海洋中。

标签: haskell random


【解决方案1】:

问题是random-1.0.1.1 中的一个错误,已在random-1.1 中修复。 The changelog 指向 this ticket。特别是指旧版本:

它还假设所有 RandomGen 实现产生的随机值范围与 StdGen 相同。

这里一次产生 8 位随机性,这导致了观察到的行为。

random-1.1 修复了这个问题:

此实现也适用于任何 RandomGen,即使是每次下一次调用只产生一点熵或具有非零的最小界限的那些。

【讨论】:

    猜你喜欢
    • 2017-11-27
    • 2021-09-19
    • 1970-01-01
    • 2012-01-18
    • 2021-12-04
    • 2014-12-14
    • 1970-01-01
    • 1970-01-01
    • 2017-04-16
    相关资源
    最近更新 更多