user1028028 - 2 years ago 194
Swift Question

# Gaussian random numbers with swift 2.1

I'm trying to update an old objective-c project to swift. I need to generate gaussian random numbers. In objective-c I used this:

``````double gaussrand()
{
static double V1, V2, S;
static int phase = 0;
double X;

if(phase == 0) {
do {
double U1 = (double)rand() / RAND_MAX;
double U2 = (double)rand() / RAND_MAX;

V1 = 2 * U1 - 1;
V2 = 2 * U2 - 1;
S = V1 * V1 + V2 * V2;
} while(S >= 1 || S == 0);

X = V1 * sqrt(-2 * log(S) / S);
} else
X = V2 * sqrt(-2 * log(S) / S);

phase = 1 - phase;

return X;
}
``````

However this doesn't translate well into swift. Anybody know a way to generate gaussian random numbers given a mean and a standard deviation in sfift 2.1?

Note that as you have defined it, you want `gaussRand` to be a computed property. Computed properties in Swift cannot store other properties, so in the example of a Swift version of your Box-Muller transformation method implementation, I've wrapped the computed property `gaussRand` in a class, and kept `s`, `v2` and `cachedNumberExists` as stored properties in this same class, allowing for every 2nd call `gaussRand` to return the cached result from previous one.

``````class MyRandomGenerator {
// stored properties
var s : Double = 0.0
var v2 : Double = 0.0
var cachedNumberExists = false

var gaussRand : Double  {
var u1, u2, v1, x : Double
if !cachedNumberExists {
repeat {
u1 = Double(arc4random()) / Double(UINT32_MAX)
u2 = Double(arc4random()) / Double(UINT32_MAX)
v1 = 2 * u1 - 1;
v2 = 2 * u2 - 1;
s = v1 * v1 + v2 * v2;
} while (s >= 1 || s == 0)
x = v1 * sqrt(-2 * log(s) / s);
}
else {
x = v2 * sqrt(-2 * log(s) / s);
}
cachedNumberExists = !cachedNumberExists
return x
}
}
``````

We assert that we get the expected results:

``````// Assert expected results
var myRandomGenerator = MyRandomGenerator()

let numGaussNumbers = 1000
var myGaussArr = [Double](count: numGaussNumbers, repeatedValue: 0.0)
for (i,_) in myGaussArr.enumerate() { myGaussArr[i] = myRandomGenerator.gaussRand }

let myMean = myGaussArr.reduce(0.0, combine: +)/Double(numGaussNumbers) // 0.0.. OK
let myVar = myGaussArr.map { pow((\$0 - myMean), 2) }.reduce(0.0, combine: +)/Double(numGaussNumbers) // ~1, O

print("(\(myMean),\(myVar))") // ~(0,1), OK
``````

OK.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download