12

In php, how can I generate a a random number assuming a normal distribution with a specific mean and standard devaition?

matronator
  • 465
  • 6
  • 13
Maggie
  • 357
  • 4
  • 11
  • 4
    This question does not show any research effort. It is important to **do your homework**. Tell us what you found and ***why*** it didn't meet your needs. This demonstrates that you've taken the time to try to help yourself, it saves us from reiterating obvious answers, and most of all it helps you get a more specific and relevant answer. [FAQ](http://stackoverflow.com/questions/how-to-ask). – John Conde Apr 11 '13 at 14:35
  • http://php.net/manual/en/function.rand.php – sybear Apr 11 '13 at 14:36
  • 2
    rand function only generates random numbers with equal probabilities, not with a normal probability disribution – Maggie Apr 11 '13 at 14:39
  • 1
    @Maggie Check my answer. It is corect, although 4 downvotes – hek2mgl Apr 11 '13 at 14:50
  • After some discussion, @Paulpro's answer seems to be the best. I would use his suggestion – hek2mgl Apr 11 '13 at 15:19
  • @Maggie I've deleted my answer as: 1) paulpro's attempt is faster (what is important for this) and 2) my example had a little bug. Think it is not useful to fix this bug as Paul's answer should fit well. Sorry for confusion ;) – hek2mgl Apr 11 '13 at 15:33
  • 1
    @Maggie - For future reference, please explain things that you've tried as well as a context for what you're trying to accomplish – Ben D Apr 11 '13 at 15:34

2 Answers2

16
function nrand($mean, $sd){
    $x = mt_rand()/mt_getrandmax();
    $y = mt_rand()/mt_getrandmax();
    return sqrt(-2*log($x))*cos(2*pi()*$y)*$sd + $mean;
}
Paul
  • 139,544
  • 27
  • 275
  • 264
  • That's much more complicated then my attempt and takes more CPU. Also working with integers will not being possible any longer. What makes it better? Can you at least explain it? have you tested it? Or at least even used? – hek2mgl Apr 11 '13 at 14:57
  • 1
    @hek2mgl I wrote a PHP extension in `C` a while back for approximating a normal distribution. I did use it heavily. I just converted my code from `C` to `PHP` for this answer. – Paul Apr 11 '13 at 14:59
  • This explains nothing. You should rethink your C extension as it could be less CPU consuming – hek2mgl Apr 11 '13 at 15:00
  • @hek2mgl It has been tested. It is very fast and consumes negligible CPU. – Paul Apr 11 '13 at 15:01
  • @hek2mgl I just compared them. On my laptop Mine is a little faster (practically negligible) taking 0.75 seconds to do 100000 runs, while yours took 1.25 seconds. I do not know which produces more normal numbers, because I don't remember the math from this approximation when I was researching it while writing the C extension. – Paul Apr 11 '13 at 15:13
  • I've tested too. At least in PHP it is faster. So I'm willing to upvote this ;) But I'm curious if it is faster in C too. Maybe it's faster in C too. I'm not longer sure at the moment. Seems that the victory is yours and you'll not have to rethink your extension. However sometimes is better to be wrong than to be right.. ;) – hek2mgl Apr 11 '13 at 15:14
  • @hek2mgl The C extension is about 3x as fast as the PHP version for this function. I'm not sure how your function as a C extension would compare to the C extension I have. Thanks for the vote. – Paul Apr 11 '13 at 15:19
  • I just know that code like `mt_rand() + mt_rand()` is much faster in C than in PHP. I hoped without this PHP related overhead, my approach, without complicated floating point calculations, could be faster. I think the MPU will be your friend. Without having MPU, my attempt would be faster – hek2mgl Apr 11 '13 at 15:22
  • 1
    Thanks, your answer gave logical results, do you have a reference for this approximation of normal distribution? – Maggie Apr 11 '13 at 15:31
  • @Maggie I cannot find where I got this from. I should have documented the extension better. – Paul Apr 11 '13 at 16:30
  • Simple and easy, thanks ! Performance is not a big issue so this is perfect – Florent Destremau Sep 24 '19 at 15:16
  • 2
    The formula being used here is called the [Box-Muller Transform](https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform) – Ben Dec 17 '19 at 15:14
2

Try using PHP's stats_rand_gen_normal function. I believe it does what you're looking for and doesn't require that you re-invent the wheel:

Generates a single random deviate from a normal distribution with mean, av, and standard deviation, sd (sd >= 0)

Ben D
  • 14,321
  • 3
  • 45
  • 59
  • 2
    That method is actually broken (incopatible with PHP 5 at least), whcih is the reason why I wrote my own extension in the first place. – Paul Apr 11 '13 at 15:06
  • 1
    I tried using this function, but it turned out that it requires a certain package, and I didn't know how to compile it. I'm a php beginner, so if you have a link that can show me how to compile the package in details, I would appreciate it. Thanks – Maggie Apr 11 '13 at 15:10
  • 1
    If what Paulpro says is true then you're not likely to be able to use it... I'll investigate and see if there's a way of using this in PHP5+ (I haven't tested) – Ben D Apr 11 '13 at 15:11
  • @BenD There was actually a fix I found for it somewhere in bugs.php.net, but I can't recall exactly what it was. I just had to change a float to an int or something small like that in the source code for the extension, but I didn't want to use a self modified extension for just that one function I needed, so I wrote code for just that one. Perhaps the bug has since been fixed. At the time it seemed like no one was maintaining the statistics package though. – Paul Apr 11 '13 at 15:17