Me doy cuenta de que el libro Swift proporcionó una implementación de un generador de números aleatorios. ¿Es la mejor práctica copiar y pegar esta implementación en el propio programa? ¿O hay una biblioteca que hace esto que podemos usar ahora?
443
Úselo
arc4random_uniform(n)
para un entero aleatorio entre 0 y n-1.Transmita el resultado a Int para que no tenga que escribir explícitamente sus vars como
UInt32
(lo que parece no Swifty).fuente
0
. En su código,diceRoll
podría ser0
. Solo digo ...Int(arc4random_uniform(6)+1)
.arc3random_uniform(n)
aUInt32(n)
si está utilizando un valor que aún no es de ese tipo.Editar: actualizado para Swift 3.0
arc4random
funciona bien en Swift, pero las funciones básicas están limitadas a tipos enteros de 32 bits (Int
es de 64 bits en iPhone 5S y Macs modernos). Aquí hay una función genérica para un número aleatorio de un tipo expresable por un literal entero:Podemos usar esta nueva función genérica para extender
UInt64
, agregar argumentos de límite y mitigar el sesgo de módulo. (Esto se levanta directamente de arc4random.c )Con eso podemos extendernos
Int64
a los mismos argumentos, lidiando con el desbordamiento:Para completar la familia ...
Después de todo eso, finalmente podemos hacer algo como esto:
fuente
var r = arc4random(UInt64)
. Por favor consejo, ¿qué quisiste decir aquí?arc4random
(definida en el primer bloque de código) con el argumentoUInt64
que es aType
.arc4random_buf
. El propósito de estas extensiones es hacer exactamente lo quearc4random_uniform
hace (mitigar el sesgo de módulo) excepto para los tipos de 64 bits.Editar para Swift 4.2
A partir de Swift 4.2, en lugar de usar la función C importada arc4random_uniform (), ahora puede usar las funciones nativas de Swift.
También puede usar
random(in:)
para obtener valores aleatorios para otros valores primitivos; como Int, Double, Float e incluso Bool.Versiones Swift <4.2
Este método generará un
Int
valor aleatorio entre el mínimo y el máximo dadosfuente
Usé este código:
fuente
random is unavailable in Swift: Use arc4random instead.
A partir de iOS 9, puedes usar las nuevas clases de GameplayKit para generar números aleatorios de varias maneras.
Tiene cuatro tipos de fuente para elegir: una fuente aleatoria general (sin nombre, hasta el sistema para elegir lo que hace), lineal congruencial, ARC4 y Mersenne Twister. Estos pueden generar entradas aleatorias, flotantes y bools.
En el nivel más simple, puede generar un número aleatorio a partir de la fuente aleatoria incorporada del sistema de esta manera:
Eso genera un número entre -2,147,483,648 y 2,147,483,647. Si desea un número entre 0 y un límite superior (exclusivo) usaría esto:
GameplayKit tiene algunos constructores convenientes integrados para trabajar con dados. Por ejemplo, puedes tirar un dado de seis lados como este:
Además, puede dar forma a la distribución aleatoria utilizando elementos como GKShuffledDistribution. Eso requiere un poco más de explicación, pero si estás interesado, puedes leer mi tutorial sobre los números aleatorios de GameplayKit .
fuente
import GameplayKit
. Swift 3 cambió la sintaxis aGKRandomSource.sharedRandom().nextInt(upperBound: 6)
Puede hacerlo de la misma manera que lo haría en C:
randomNumber
se infiere que es de tipoUInt32
(un entero sin signo de 32 bits)fuente
rand
,arc4random
,drand48
y amigos están todos en elDarwin
módulo. Ya se importó para usted si está creando una aplicación Cocoa, UIKit o Foundation, pero lo necesitaráimport Darwin
en los parques infantiles.Utilizar
arc4random_uniform()
Uso:
arc4random_uniform(someNumber: UInt32) -> UInt32
Esto le da enteros aleatorios en el rango
0
desomeNumber - 1
.El valor máximo para
UInt32
4,294,967,295 (es decir,2^32 - 1
).Ejemplos:
Lanzamiento de moneda
Tirada de dados
Día aleatorio en octubre
Año aleatorio en la década de 1990
Forma general:
donde
number
,max
ymin
estánUInt32
.Qué pasa...
arc4random ()
También puede obtener un número aleatorio mediante el uso
arc4random()
, que produceUInt32
entre 0 y 2 ^ 32-1. Por lo tanto, para obtener un número aleatorio entre0
yx-1
, puede dividirlo entrex
y tomar el resto. O, en otras palabras, use el operador restante (%) :Sin embargo, esto produce un ligero sesgo de módulo (ver también aquí y aquí ), por eso
arc4random_uniform()
se recomienda.Conversión ay desde
Int
Normalmente estaría bien hacer algo como esto para convertir de ida y vuelta entre
Int
yUInt32
:Sin embargo, el problema es que
Int
tiene un rango de-2,147,483,648...2,147,483,647
sistemas de 32 bits y un rango de-9,223,372,036,854,775,808...9,223,372,036,854,775,807
sistemas de 64 bits. Compare esto con elUInt32
rango de0...4,294,967,295
. ElU
deUInt32
significa sin firmar .Considere los siguientes errores:
Por lo tanto, solo debe asegurarse de que sus parámetros de entrada estén dentro del
UInt32
rango y que tampoco necesite una salida que esté fuera de ese rango.fuente
Ejemplo para un número aleatorio entre 10 (0-9);
Código muy fácil, simple y corto.
fuente
Solo he podido usar
rand()
para obtener un CI aleatorio. Puedes convertirlo en Int usando algo como esto:Puede usar su función aleatoria C favorita y simplemente convertirla en valor a Int si es necesario.
fuente
random()
, que devuelve un enInt
lugar deUInt32
, y como @SomeGuy mencionó, simplemente llamesrandom(arc4random())
una vez en cualquier lugar antes de usarlo para asegurarse de que tenga una semilla aleatoria diferente para cada ejecución de su programa.La respuesta de @ jstn es buena, pero un poco detallada. Swift se conoce como un lenguaje orientado al protocolo, por lo que podemos lograr el mismo resultado sin tener que implementar un código repetitivo para cada clase en la familia de enteros, agregando una implementación predeterminada para la extensión del protocolo.
Ahora podemos hacer:
y todas las demás clases de enteros están bien.
fuente
En Swift 4.2 puede generar números aleatorios llamando al
random()
método en cualquier tipo numérico que desee, proporcionando el rango con el que desea trabajar. Por ejemplo, esto genera un número aleatorio en el rango de 1 a 9, inclusive en ambos ladosTambién con otros tipos.
fuente
Aquí hay una biblioteca que hace bien el trabajo https://github.com/thellimist/SwiftRandom
fuente
fuente
Me gustaría agregar a las respuestas existentes que el ejemplo del generador de números aleatorios en el libro de Swift es un Generador de congruencia lineal (LCG), es muy limitado y no debería ser excepto por los ejemplos triviales, donde la calidad de la aleatoriedad no No importa en absoluto. Y un LCG nunca debe usarse con fines criptográficos .
arc4random()
es mucho mejor y puede usarse para la mayoría de los propósitos, pero nuevamente no debe usarse para propósitos criptográficos.Si desea algo que garantice su seguridad criptográfica, úselo
SecCopyRandomBytes()
. Tenga en cuenta que si construye un generador de números aleatorios en algo, alguien más podría terminar (mal) usándolo con fines criptográficos (como contraseña, clave o generación de sal), entonces debería considerar usarlo deSecCopyRandomBytes()
todos modos, incluso si su necesidad no lo hace. No es necesario eso.fuente
Desde Swift 4.2
Hay un nuevo conjunto de API:
Todos los tipos numéricos ahora tienen el
random(in:)
método que tomarange
.Devuelve un número uniformemente distribuido en ese rango.
TL; DR
Bueno, ¿qué hay de malo en la "buena" vieja manera?
Debe usar las API de C importadas (son diferentes entre plataformas) .
Y además...
Si usa
arc4random()
(para calcular el resto) comoarc4random() % aNumber
, el resultado no se distribuye uniformemente entre el0
yaNumber
. Hay un problema llamado sesgo de módulo .Sesgo de módulo
Normalmente, la función genera un número aleatorio entre
0
y MAX (depende del tipo, etc.) . Para hacer un ejemplo rápido y fácil, digamos que el número máximo es7
y le importa un número aleatorio en el rango0 ..< 2
(o el intervalo [0, 3) si lo prefiere) .Las probabilidades para números individuales son:
En otras palabras, es más probable que termines con 0 o 1 que 2 . Por supuesto, tenga en cuenta que esto es extremadamente simplificado y que el número MAX es mucho más alto, lo que lo hace más "justo".
fuente
Sin arc4Random_uniform () en algunas versiones de Xcode (en 7.1 se ejecuta pero no se completa automáticamente para mí). Puedes hacer esto en su lugar.
Para generar un número aleatorio de 0-5. primero
Entonces
fuente
Aquí 5 se asegurará de que el número aleatorio se genere de cero a cuatro. Puede establecer el valor en consecuencia.
fuente
Swift 4.2
Adiós para importar Foundation C lib
arc4random_uniform()
Más @ articulo.mercadolibre.com.ar
fuente
El siguiente código producirá un número aleatorio seguro entre 0 y 255:
Lo llamas así:
Para números más grandes se vuelve más complicado.
Esto es lo mejor que se me ocurrió:
Estos métodos usan un número aleatorio adicional para determinar cuántos
UInt8
s se utilizarán para crear el número aleatorio. La última línea convierte el[UInt8]
aUInt16
oUInt32
.No sé si los dos últimos todavía cuentan como verdaderamente aleatorio, pero puedes modificarlo a tu gusto :)
fuente
Swift 4.2
Swift 4.2 ha incluido una API de números aleatorios nativa y bastante completa en la biblioteca estándar. ( Propuesta de Swift Evolution SE-0202 )
Todos los tipos de números tienen el estático aleatorio (en :) que toma el rango y devuelve el número aleatorio en el rango dado
fuente
Para iOS, macOS y tvOS, puede usar una fuente aleatoria de todo el sistema en el marco de Xcode
GameKit
. Aquí puede encontrar laGKRandomSource
clase con susharedRandom()
método de clase:O simplemente use un
randomElement()
método que devuelva un elemento aleatorio de la colección:fuente
Puedes usar
GeneratorOf
así:fuente
Yo uso este código para generar un número aleatorio:
fuente
Detalles
xCode 9.1, Swift 4
Solución orientada a las matemáticas (1)
Uso de la solución (1)
Solución orientada a programadores (2)
Uso de la solución (2)
Muestra completa
Resultado de la muestra
fuente