简体   繁体   中英

Random number generator in haskell using recursion

I have the following exercise :

In many computer programs, we need a random number generator. The numbers produced by these generators are not really random, but they appear to be random. This explains why these generators are sometimes called pseudo-random generators. One of the simplest generators of this type is the so-called linear congruential generator s. These generators produce a series of numbers X_i using the recurrence X_i+1 = (a · X_i + c) mod m. The values for the parameters a, c, and m must be chosen wisely. If you are interested in how to choose these values, then you may want to read https://en.wikipedia.org/wiki/Linear_congruential_generator .

In this exercise, we choose X_0 = 2773639, a = 25214903917, c = 11, and m = 2^45. Give a Haskell implementation of the infinite list random :: [Integer] that returns the infinite list of random numbers generated by this set of parameters. The time complesxity of take n random should be linear in n. The expression take 6 random should result in: [2773639,25693544934790,35087648281,25863180521136,928172761339,19643099434218]

I'm new to Haskell and I'm not sure how to generate an infinite list and even what the parameters of this function should be. Moreover, the recursivity makes it even harder as I am not sure how to write the base case. So far I have tried this:

random :: Int -> [a]

random 0 = 2773639
random x = [x | x <- (25214903917 * random (x-1) + 11 ) `mod` (2^45)]

Which is obviously flawed, but I can't come up with something else, as I don't have enough experience in Haskell to even think about other possibilities. Thank you for your time!

I was able to solve it with that code:

random :: [Integer] 

random = f 2773639 
       where f x = x : f((25214903917 * x + 11) `mod` (2^45)) 

Your approach is one option; a somewhat cleaner way is

random :: [Integer] 
random = iterate (\x -> (25214903917 * x + 11) `mod` 2^45) 2773639

or, using point-free style,

random = iterate ((`mod` 2^45) . (+11) . (25214903917*)) 2773639

I would remark that, since your congruence is only 45 bits, you don't need to use Integer here, Int (or, to be platform-safe, Data.Int.Int64 ) is enough and better because it's faster and hints at how roughly large the numbers actually are that come out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM