3

我需要生成一些随机数用于测试目的。我以前从未使用过 Data.Random。我需要做很多测试,我不会提前知道我需要多少数字,但我会知道它们应该落入一定的范围内。我写了这个函数:

import System.Random

f k = (\(x,y) -> x*y < (10^k) && x*y >0 )

rands n g k = take n $ filter (\(x,y) -> x*y < (10^k) && x*y >0 ) (zip a b) 
    where a = randomRs (1::Int, 10^k-1) ga 
          b = randomRs (1::Int, 10^k-1) gb
          (ga, gb) = split $ mkStdGen g

并开始使用它生成的数字来测试事物。使用这个功能时,我开始注意到奇怪的事情:

testRands n k = do
    g1 <- randomIO
    g2 <- randomIO
    let r = rands n (mkStdGen g1, mkStdGen g2) k
    putStrLn $ show r 
    putStrLn $ show $ map (\(x,y) -> x*y < 10^k && x*y >0) r  
    putStrLn $ show $ map (\(x,y) -> x*y) r
    putStrLn $ show $ maximum $ map (\(x,y) -> x*y) r

*Main> testRands 4 7
[(6193574,9385226),(9634973,5475375),(5070277,7408626),(3801396,5652588)]
[True,True,True,True]
[4353660,6993107,2038586,4030960]
6993107

然后我复制它生成的数字并将它们粘贴回 GHCI 并在所有数字上调用完全相同的谓词函数:

*Main> map (f 7) [(6193574,9385226),(9634973,5475375),(5070277,7408626),(3801396,5652588)]
[False,False,False,False]

这毫无意义,我什至不知道从哪里开始尝试修复它。

4

2 回答 2

8

在您的程序中,您在以下行中显式生成 type 的值Int

where a = randomRs (1::Int, 10^k-1) ga 
      b = randomRs (1::Int, 10^k-1) gb

如果您使用的是 32 位机器,则生成的数字相乘可能会导致溢出。例如:

> 6193574 * 9385226 :: Int
4353660

但是,文字本身是重载的。因此,如果您将它们粘贴到 GHCi 中,则它们默认为(无界)Integer类型,它们不会溢出:

> 6193574 * 9385226 :: Integer
58128091737724

这解释了应用谓词的困难结果。

因此,要么生成Integer而不是Int,要么添加类型注释,说明您传递的列表是[Int]而不是[Integer]使结果匹配。

于 2013-05-31T15:27:19.060 回答
4

您正在运行 32 位 GHC:

Prelude Data.Int> uncurry (*) (6193574,9385226) :: Int32
4353660

因此,由于您Int的 s 是 32 位,因此由于溢出,乘积小于限制。

a = randomRs (1::Int, 10^k-1) ga 

但是当你

*Main> map (f 7) [(6193574,9385226),(9634973,5475375),(5070277,7408626),(3801396,5652588)]
[False,False,False,False]

类型不受限制Int,因此默认为Integer,因此没有溢出,并且产品大于限制..

于 2013-05-31T15:27:41.273 回答