Saltar al contenido

Generar números aleatorios con una distribución dada

Queremos enseñarte la mejor información que encontramos on line. Deseamos que te sirva de ayuda y si deseas comentarnos algún detalle que nos pueda ayudar a perfeccionar nuestra información hazlo con total libertad.

Solución:

Esta es una implementación de Swift fuertemente influenciada por las diversas respuestas a Generar números aleatorios con una distribución (numérica) dada.

Para Rápido 4.2/Xcode 10 y más tarde (explicaciones en línea):

func randomNumber(probabilities: [Double]) -> Int 

    // Sum of all probabilities (so that we don't have to require that the sum is 1.0):
    let sum = probabilities.reduce(0, +)
    // Random number in the range 0.0 <= rnd < sum :
    let rnd = Double.random(in: 0.0 ..< sum)
    // Find the first interval of accumulated probabilities into which `rnd` falls:
    var accum = 0.0
    for (i, p) in probabilities.enumerated() 
        accum += p
        if rnd < accum 
            return i
        
    
    // This point might be reached due to floating point inaccuracies:
    return (probabilities.count - 1)

Ejemplos:

let x = randomNumber(probabilities: [0.2, 0.3, 0.5])

devuelve 0 con probabilidad 0,2, 1 con probabilidad 0,3 y 2 con probabilidad 0,5.

let x = randomNumber(probabilities: [1.0, 2.0])

devuelve 0 con probabilidad 1/3 y 1 con probabilidad 2/3.


Para Rápido 3/Xcode 8:

func randomNumber(probabilities: [Double]) -> Int 

    // Sum of all probabilities (so that we don't have to require that the sum is 1.0):
    let sum = probabilities.reduce(0, +)
    // Random number in the range 0.0 <= rnd < sum :
    let rnd = sum * Double(arc4random_uniform(UInt32.max)) / Double(UInt32.max)
    // Find the first interval of accumulated probabilities into which `rnd` falls:
    var accum = 0.0
    for (i, p) in probabilities.enumerated() 
        accum += p
        if rnd < accum 
            return i
        
    
    // This point might be reached due to floating point inaccuracies:
    return (probabilities.count - 1)


Para Rápido 2/Xcode 7:

func randomNumber(probabilities probabilities: [Double]) -> Int 

    // Sum of all probabilities (so that we don't have to require that the sum is 1.0):
    let sum = probabilities.reduce(0, combine: +)
    // Random number in the range 0.0 <= rnd < sum :
    let rnd = sum * Double(arc4random_uniform(UInt32.max)) / Double(UInt32.max)
    // Find the first interval of accumulated probabilities into which `rnd` falls:
    var accum = 0.0
    for (i, p) in probabilities.enumerate() 
        accum += p
        if rnd < accum 
            return i
        
    
    // This point might be reached due to floating point inaccuracies:
    return (probabilities.count - 1)

¿Existe una forma más agradable y limpia de elegir un número aleatorio con una cierta probabilidad cuando se tiene que considerar una gran cantidad de probabilidades?

Por supuesto. Escribe una función que genere un número basado en una tabla de probabilidades. Eso es esencialmente lo que es la declaración de cambio que ha señalado: una tabla definida en el código. Podría hacer lo mismo con los datos usando una tabla que se define como una lista de probabilidades y resultados:

probability    outcome
-----------    -------
   0.4            1
   0.2            2
   0.1            3
   0.15           4
   0.15           5

Ahora puedes elegir un número entre 0 y 1 al azar. Comenzando desde la parte superior de la lista, sume las probabilidades hasta que haya excedido el número que eligió y use el resultado correspondiente. Por ejemplo, supongamos que el número que elige es 0,6527637. Comience en la parte superior: 0.4 es más pequeño, así que continúe. 0,6 (0,4 + 0,2) es más pequeño, así que continúa. 0,7 (0,6 + 0,1) es mayor, así que detente. El resultado es 3.

Mantuve la tabla corta aquí en aras de la claridad, pero puede hacerla tan larga como desee y puede definirla en un archivo de datos para que no tenga que volver a compilar cuando cambie la lista.

Tenga en cuenta que no hay nada particularmente específico para Swift sobre este método: puede hacer lo mismo en C o Swift o Lisp.

Esta parece una buena oportunidad para un complemento desvergonzado de mi pequeña biblioteca, swiftstats: https://github.com/r0fls/swiftstats

Por ejemplo, esto generaría 3 variables aleatorias a partir de una distribución normal con media 0 y varianza 1:

import SwiftStats
let n = SwiftStats.Distributions.Normal(0, 1.0)
print(n.random())

Las distribuciones admitidas incluyen: normal, exponencial, binomial, etc.

También admite el ajuste de datos de muestra a una distribución determinada, utilizando el Estimador de máxima verosimilitud para la distribución.

Consulte el archivo Léame del proyecto para obtener más información.

Aquí tienes las comentarios y valoraciones

Eres capaz de añadir valor a nuestro contenido cooperando tu veteranía en las críticas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *