Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Code to generate Gaussian (normally distributed) random numbers in Ruby

What is some code to generate normally distributed random numbers in ruby?

(Note: I answered my own question, but I'll wait a few days before accepting to see if anyone has a better answer.)

EDIT:

Searching for this, I looked at all pages on SO resulting from the two searches:

+"normal distribution" ruby

and

+gaussian +random ruby

like image 876
Eponymous Avatar asked Apr 28 '11 22:04

Eponymous


People also ask

How do you generate random numbers in Ruby?

In Ruby, there are many ways to generate random numbers with various properties. The rand method can be used in 3 ways: Without arguments, rand gives you a floating point number between 0 & 1 (like 0.4836732493) With an integer argument ( rand(10) ) you get a new integer between 0 & that number.

Is Gaussian distribution random?

. A random variable with a Gaussian distribution is said to be normally distributed, and is called a normal deviate. Normal distributions are important in statistics and are often used in the natural and social sciences to represent real-valued random variables whose distributions are not known.

What is Rand in Ruby?

Ruby | Random rand() function Random#rand() : rand() is a Random class method which generates a random value. Syntax: Random.rand() Parameter: Random values. Return: generates a random value.


1 Answers

Python's random.gauss() and Boost's normal_distribution both use the Box-Muller transform, so that should be good enough for Ruby too.

def gaussian(mean, stddev, rand)   theta = 2 * Math::PI * rand.call   rho = Math.sqrt(-2 * Math.log(1 - rand.call))   scale = stddev * rho   x = mean + scale * Math.cos(theta)   y = mean + scale * Math.sin(theta)   return x, y end 

The method can be wrapped up in a class that returns the samples one by one.

class RandomGaussian   def initialize(mean, stddev, rand_helper = lambda { Kernel.rand })     @rand_helper = rand_helper     @mean = mean     @stddev = stddev     @valid = false     @next = 0   end    def rand     if @valid then       @valid = false       return @next     else       @valid = true       x, y = self.class.gaussian(@mean, @stddev, @rand_helper)       @next = y       return x     end   end    private   def self.gaussian(mean, stddev, rand)     theta = 2 * Math::PI * rand.call     rho = Math.sqrt(-2 * Math.log(1 - rand.call))     scale = stddev * rho     x = mean + scale * Math.cos(theta)     y = mean + scale * Math.sin(theta)     return x, y   end end 

CC0(CC0)

To the extent possible under law, antonakos has waived all copyright and related or neighboring rights to the RandomGaussian Ruby class. This work is published from: Denmark.

like image 59
antonakos Avatar answered Oct 05 '22 23:10

antonakos