tamaño numeros metodos lista largo funciones elemento crear como arreglos arreglo aleatorios agregar ruby random normal-distribution

metodos - numeros aleatorios ruby



Código para generar números aleatorios gaussianos(normalmente distribuidos) en Ruby (4)

+1 en la respuesta de @ antonakos. Aquí está la implementación de Box-Muller que he estado usando; es un código esencialmente idéntico pero un poco más ajustado:

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 = !@compute_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

Por supuesto, si realmente te importa la velocidad, deberías implementar el Algoritmo Ziggurat :).

¿Qué es un código para generar números aleatorios distribuidos normalmente en ruby?

(Nota: respondí mi propia pregunta, pero esperaré unos días antes de aceptar ver si alguien tiene una mejor respuesta).

EDITAR:

Buscando esto, miré todas las páginas en SO resultantes de las dos búsquedas:

+ rubí de "distribución normal"

y

+ rubí gaussiano + aleatorio


La pregunta original pedía un código, pero el comentario de seguimiento del autor implicaba un interés en el uso de las bibliotecas existentes. Estaba interesado en lo mismo, y mis búsquedas encontraron estas dos gemas de rubí:

gsl - "Interfaz Ruby para la Biblioteca Científica GNU" (requiere que instale GSL). La secuencia de llamada para números aleatorios normalmente distribuidos con media = 0 y una desviación estándar dada es

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

rubystats - "un puerto de las bibliotecas de estadísticas de PHPMath" (ruby puro). La secuencia de llamada para números aleatorios distribuidos normalmente con una media dada y una desviación estándar es

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


Otra opción, esta usando la gema de distribution , escrita por uno de los becarios de SciRuby.

Es un poco más fácil de usar, creo.

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


Python''s random.gauss() y Boost''s normal_distribution usan la transformación Box-Muller , así que eso también debería ser suficiente para 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

El método puede completarse en una clase que devuelva las muestras una a una.

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)

En la medida de lo posible, conforme a la ley, antonakos ha renunciado a todos los derechos de autor y derechos relacionados o relacionados a la clase RandomGaussian Ruby. Este trabajo se publica desde: Dinamarca.

La declaración de la licencia no significa que me importa este código. Por el contrario, no uso el código, no lo he probado y no programo en Ruby.