4

I would like to generate numbers into an array that has normal distribution. Is there any function in objective-c or c that can help to get the result easily without any math?

JFS
  • 2,992
  • 3
  • 37
  • 48
Infinite Possibilities
  • 7,415
  • 13
  • 55
  • 118

2 Answers2

4

Use the the Box-Muller-Transformation:

1.) you need two uniform distributed random numbers u and v as doubles in the interval (0,1] (0 needs to be excluded):

double u =(double)(random() %100000 + 1)/100000; //for precision
double v =(double)(random() %100000 + 1)/100000; //for precision

2.) calculate the uniform distributed value with average of 0 and the standard deviation sigma of 1:

double x = sqrt(-2*log(u))*cos(2*pi*v);   //or sin(2*pi*v)

3.) if needed add sigma and average for your target distribution like this:

double y = x * sigmaValue + averageValue;

4.) put it in an array

[randomNumberArray addObject:[NSNumber numberWithDouble:y]]

There is no function norminv for objc. So, math is needed here.

Edit: I like using random() to be able to seed the random value generator

JFS
  • 2,992
  • 3
  • 37
  • 48
  • This is really a great solution, but one questions: will this order the numbers? – Infinite Possibilities Mar 03 '13 at 20:30
  • Unfortunately it won't. And (for large arrays) please consider to check and exclude u and v for the value 0 and 1. Otherwise the log-function won't work. – JFS Mar 03 '13 at 20:39
  • What is wrong with sorting it with `[randomNumberArray sortedArrayUsingSelector:@selector(compare:)]` afterwards? – JFS Mar 04 '13 at 07:25
  • @JFS, is it suppose to have negative numbers? – dwbrito May 18 '13 at 13:55
  • 1
    @dwbrito, it will generate negative numbers as well. If you follow the equations until step 2 it will generate normal distributed values with the average of zero (example: http://www.regentsprep.org/Regents/math/algtrig/ATS2/normal67.gif). So, there will be positive and negative values. – JFS May 20 '13 at 08:54
  • @JFS, I thought it was only negative. I ended up using the Ziggurat algorithm – dwbrito May 20 '13 at 09:52
  • 1
    @dwbrito, no it is not just generating negative values. The Ziggurat algorithm is actually similar but not as easy to implement than the Box-Muller transformation. – JFS May 20 '13 at 17:50
2

Let me preface this by saying, please, correct me if I'm wrong!

It's my understanding that the Box-Muller Transformation relies on the source numbers being them selves uniformly distributed, thus using random() or rand() as the source data-set for Box-Muller will NOT necessarily produce a uniform distribution.

It is instead intended to take a generic set of uniformly distributed random numbers, and produce independent pairs of random numbers uniformly distributed in a 2D coordinate system.

Wikipedia: Box-Muller Transform


There is however another way:

On most Unix systems (and thus Objective C on iOS or OSX) using the rand48 library of functions:

Reference: drand

double drand48(void);
void srand48(long int seedval);

srand48() seeds the generator, and drand48() produces random numbers uniformly distributed over the interval [0.0 - 1.0]

Adam
  • 25,966
  • 23
  • 76
  • 87
  • thank you for the interesting discussion. As long as there are two independent uniform distributed values in the interval of (0,1] the Box-Muller approach should generate normal distributed values. But I agree that the source quality for random number generator has an effect on the results. I don't like the quality of `random()` but I need to create the same sequence with normal distributed numbers. That's why I can't use arc4random() or other better approaches. How would I implement these Unix function in iOS? – JFS Sep 06 '13 at 08:04
  • srand48() and drand48() functions are available in iOS as @Adam said. – Borzh Nov 20 '15 at 18:03