Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
697 views
in Technique[技术] by (71.8m points)

random - Swift - Seeding arc4random_uniform? Or alternative?

Let me start by stating what I'm trying to accomplish:

  1. I need to randomly generate a set of numbers within a range
  2. I would like those numbers to be somewhat uniformly distributed
  3. I need to be able to seed the random number generation such that, given a seed, the resulting random numbers will always be the same.

After experimenting quite a bit with drand48(), rand() and arc4random(), I have currently settled on using rand() for obtaining a random number, and srand() for seeding. Here is a small example simplified from what I am doing:

let seed: UInt32 = 10
srand(seed)
let start = 0
let end = 100
let randomNumber = Double(rand()) % (end + 1 - start) + start

This works. Given the same seed, the same random number comes out. Performing multiple randomNumber calculations results in multiple, different random numbers coming out. Re-seeding via srand starts the "randomness" over again.

The only downside is rand() is not uniformly distributed. Indeed I pretty much always end up with a set of numbers that are linearly increasing for the most part.

It sounds like arc4random_uniform will generate more of a uniform random output, however from my research it isn't possible to seed arc4random, as it seeds itself the first time it is invoked and isn't necessarily "designed" to be seeded externally.

So my question; is there a better alternative to srand() / rand() that will still give me the same outputs for a given seed, but those outputs are more uniformly distributed?

Thanks, - Adam

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I know "GameKit" sounds like it's just for games, but it contains a serious random number generation system. I suggest you take a look at GKMersenneTwisterRandomSource and GKRandomDistribution. The GKMersenneTwisterRandomSource takes a random seed (if you so choose) and the GKRandomDistribution class implements a Uniform Distribution. Used together, they do exactly what you're looking for.

import GameKit

// The Mersenne Twister is a very good algorithm for generating random
// numbers, plus you can give it a seed...    
let rs = GKMersenneTwisterRandomSource()
rs.seed = 1780680306855649768

// Use the random source and a lowest and highest value to create a 
// GKRandomDistribution object that will provide the random numbers.   
let rd = GKRandomDistribution(randomSource: rs, lowestValue: 0, highestValue: 100)

// Now generate 10 numbers in the range 0...100:    
for _ in 1...10 {
    print(rd.nextInt())
}

print("---")

// Let's set the seed back to the starting value, and print the same 10
// random numbers.    
rs.seed = 1780680306855649768
for _ in 1...10 {
    print(rd.nextInt())
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...