2011-04-28 130 views
26

在ruby中生成正态分布随机数的代码是什么?Ruby中生成高斯(正态分布)随机数的代码

(注:我回答我自己的问题,但接受,看看是否有人有一个更好的答案之前,我会等待几天。)

编辑:

搜索此,我看着所有网页上,来自这两个搜索这样造成:

+“正态分布”红宝石

+高斯+随机红宝石

+0

检查相关的问题(见右侧面板)? – Gumbo 2011-04-28 22:19:56

+0

是的,我查了一下,虽然有些地方有算法,但没有人用Ruby编码它。这是一个常见的任务,它确实应该在标准库中。但是如果没有这样做,我认为StackOverflow上应该可以找到复制粘贴代码。 – Eponymous 2011-04-28 22:26:18

+0

提一下你所查的内容可能是一个好主意,这样思考回答的人就不会检查他们,除非他们认为你错过了某些东西。 – 2011-04-28 23:34:27

回答

43

Python的random.gauss()和Boost的normal_distribution都使用Box-Muller transform,所以对于Ruby来说也应该足够好。

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 

该方法可以封装在一个类中,该类可以逐个返回样本。

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)

下法律允许的范围内,antonakos已放弃所有版权及相关或邻接权的RandomGaussian Ruby类。这项工作发表于:丹麦。


许可证声明并不意味着我关心此代码。相反,我不使用代码,我没有测试它,并且我不用Ruby编程。

+0

您可以为您的代码添加许可许可证(BSD/CC-0或其他)(因为它旨在用于粘贴重用​​) – Eponymous 2011-05-31 20:57:28

+4

@同名完成。 – antonakos 2011-06-01 16:41:38

+2

只提供给sig块;) – drewish 2013-11-26 19:31:40

19

原始问题要求提供代码,但作者的后续评论意味着使用现有库的兴趣。我对同样的感兴趣,我的搜索发现了这两个宝石:

gsl - “Ruby接口到GNU科学图书馆”(需要你安装GSL)。对于均值= 0和给定的标准偏差的正态分布的随机数的调用序列是

rng = GSL::Rng.alloc 
rng.gaussian(sd)  # a single random sample 
rng.gaussian(sd, 100) # 100 random samples 

rubystats - “从PHPMath统计库的端口”(纯红宝石)。具有给定均值和标准差的正态分布随机数的呼叫顺序为

gen = Rubystats::NormalDistribution.new(mean, sd) 
gen.rng    # a single random sample 
gen.rng(100)   # 100 random samples 
10

@ antonakos的回答+1。以下是我一直使用的Box-Muller的实现;它本质上是相同的,但略有收紧代码:

class RandomGaussian 
    def initialize(mean = 0.0, sd = 1.0, rng = lambda { Kernel.rand }) 
    @mean, @sd, @rng = mean, sd, rng 
    @compute_next_pair = false 
    end 

    def rand 
    if (@compute_next_pair = [email protected]_next_pair) 
     # Compute a pair of random values with normal distribution. 
     # See http://en.wikipedia.org/wiki/Box-Muller_transform 
     theta = 2 * Math::PI * @rng.call 
     scale = @sd * Math.sqrt(-2 * Math.log(1 - @rng.call)) 
     @g1 = @mean + scale * Math.sin(theta) 
     @g0 = @mean + scale * Math.cos(theta) 
    else 
     @g1 
    end 
    end 
end 

当然,如果你真的关心速度,你应该实现Ziggurat Algorithm :)。

8

另一种选择,这一个使用distribution宝石,由一个SciRuby研究员编写。

我觉得使用起来有点简单。

require 'distribution' 
normal = Distribution::Normal.rng(1) 
norm_distribution = 1_000.times.map {normal.call} 
+0

看着这段代码,我不知道预期的标准偏差应该是什么。 – 2013-12-10 20:10:03

+1

转到此处:http://rubydoc.info/gems/distribution/0.7.0/Distribution/Normal/Ruby_ 您会看到rng(1)指定了平均值,并且您可以指定标准偏差你想通过传递额外的参数'Distribution :: Normal.rng(mean,standard_deviation)'来调用该分配中的随机值。 – Ryanmt 2013-12-19 20:24:32

+0

正确的链接是:[distribution](https://rubygems.org/gems/distribution) – pisaruk 2014-11-15 19:26:14

相关问题