Code to generate Gaussian (normally distributed) random numbers in Ruby
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)
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.
Normally distributed random variables on Ruby on Rails
Thanks for the help in comments. Oli is right, I found the answer in that answer :
https://stackoverflow.com/a/8205982/2576033
Using rubystats gem - "a port of the statistics libraries from PHPMath" (pure ruby), you can generate normally distributed variables, easily and in a nice way :
gen = Rubystats::NormalDistribution.new(mean, sd)
gen.rng # a single random sample
gen.rng(100) # 100 random samples
Generate a perfectly normally distributed sample of size n in R
You can use the bayestestR package:
library(bayestestR)
x <- rnorm_perfect(n = 100, mean = 0, sd = 1)
plot(density(x))
Generate random value from list of numbers
Just use Array#sample
:
[100, 643, 826, 804, 372, 076, 156, 152, 036, 248].sample
Available in Ruby 1.9.1+. In an earlier version of Ruby, you could
require 'backports/1.9.1/array/sample'
Simulating averages of normally-distributed random variables in R
Your correct calculation is the first one, where you are generating new realizations of the normal random variable when averaging, as opposed to using the realizations generated in the previous step.
In fact, the distribution of O2
assumes that the two normal random variables being averaged are mutually independent.
In your second calculation, this is not true, as you are averaging v1
and v2
, which are not independent since both depend on o1
. This is why you get larger variances in the second case.
Generate normally distributed data within a range using Fortran
There are different ways to sample from a truncated normal distribution. The "best" way depends on your mean and variance.
A simple way is just plain rejection: generate a deviate and if it's too big or small throw it away and repeat. If your parameters are such that you don't reject many this is a good method.
For the routine specified, doing this rejection is simple: sticking the whole calculation part (including the flag
test) into a do
...end do
loop with an if (abs(normal).lt.10) exit
should do it.
[This isn't elegant, and extra bookkeeping may be required, with samples being generated as pairs. But, again, if rejection happens rarely that's not too bad. Tidying is left as an exercise for the reader.]
That's how one may change the routine, but as @george comments, that probably isn't the best approach, even with the rejection. Certainly, having a function called normal
which takes mean
and sigma
and returns a deviate which isn't from a normal distribution could be confusing.
function truncated_normal(mu, sigma, lim_a, lim_b) !Very side-effecty
... declarations ...
if ( ... test for wanting the rejection method ... ) then
do
truncated_normal = normal(mu, sigma)
if (truncated_normal.gt.lim_a.and.truncated_normal.lt.lim_b) exit
end do
else
... the other magical method when rejection is too likely ...
end if
end
Build a C++ normal distributed random number generator on Xcode 8.3
It is defined as
template< class RealType = double > class normal_distribution
where for RealType
you could use only float, double or long double, otherwise it is undefined.
Code should be
std::normal_distribution<double> distribution (0.0, 1.0);
double random_value = distribution(e2);
return fabs(random_value);
Related Topics
Ruby on Rails: What Reporting And/Or Charting Tools Are Available
When Is It Better to Use a Struct Rather Than a Hash in Ruby
Don't Create View Folder on Rails Generate Controller
Better Way to Turn a Ruby Class into a Module Than Using Refinements
Rails: How to Determine Controller/Action in View
Rails Activeadmin - Custom Association Select Box
How to Read the Body Text of an Email Using Ruby's Net/Imap Library
How to Test a Ruby Application Which Uses Mechanize
What's the Difference Between a Class and the Singleton of That Class in Ruby
Creating an Empty File in Ruby: "Touch" Equivalent
How to Generate a Random Date in Ruby
Using Ruby's Optionparser to Parse Sub-Commands
Sorting a Two-Dimensional Array by Second Value
Is Ruby a Scripting Language or an Interpreted Language
$Redis Global Variable with Ruby on Rails