Estoy tratando de generar un número aleatorio que esté entre 0 y 1. Sigo leyendo arc4random()
, pero no hay ninguna información sobre cómo obtener un flotador. ¿Cómo hago esto?
ios
c
random
floating-point
arc4random
jini
fuente
fuente
Respuestas:
Valor aleatorio en [0, 1 [ (incluido 0, excluido 1):
double val = ((double)arc4random() / UINT32_MAX);
Un poco más de detalles aquí .
El rango real es [0, 0.999999999767169356] , ya que el límite superior es (doble) 0xFFFFFFFF / 0x100000000.
fuente
ARC4RANDOM_MAX
tenga que definirse manualmente, pero0x100000000
es 4294967296 , que esULONG_MAX + 1
. ¿Dónde está documentado quearc4random()
es máximo deULONG_MAX
todos modos?// Seed (only once) srand48(time(0)); double x = drand48(); // Swift version // Seed (only once) srand48(Int(Date().timeIntervalSince1970)) let x = drand48()
fuente
drand48
debe inicializarse una vez con una semilla. La documentación de Apple también sugiere que debe inicializarse.double
. Consulte stackoverflow.com/a/34765674/1033581 sobre cómo lograr la mejor precisión.Para Swift 4.2+, consulte: https://stackoverflow.com/a/50733095/1033581
A continuación se presentan recomendaciones para una uniformidad correcta y una precisión óptima para ObjC y Swift 4.1.
Precisión de 32 bits (óptima para
Float
)Valor aleatorio uniforme en [0, 1] (incluidos 0.0 y 1.0), hasta 32 bits de precisión:
Obj-C :
float val = (float)arc4random() / UINT32_MAX;
Rápido :
Es óptimo para:
Float
(oFloat32
) que tiene una precisión significativa de 24 bits para su mantisaPrecisión de 48 bits (desaconsejado)
Es fácil lograr una precisión de 48 bits con
drand48
( que se usaarc4random_buf
debajo del capó ). Pero tenga en cuenta que drand48 tiene fallas debido al requisito de semilla y también por no ser óptimo para aleatorizar los 52 bits de la mantisa doble.Valor aleatorio uniforme en [0, 1] , precisión de 48 bits:
Rápido :
// seed (only needed once) srand48(Int(Date.timeIntervalSinceReferenceDate)) // random Double value let val = drand48()
Precisión de 64 bits (óptima para
Double
yFloat80
)Valor aleatorio uniforme en [0, 1] (incluidos 0,0 y 1,0), precisión de hasta 64 bits:
Swift , usando dos llamadas a arc4random:
let arc4random64 = UInt64(arc4random()) << 32 &+ UInt64(arc4random()) let val = Float80(arc4random64) / Float80(UInt64.max)
Swift , usando una llamada a arc4random_buf:
var arc4random64: UInt64 = 0 arc4random_buf(&arc4random64, MemoryLayout.size(ofValue: arc4random64)) let val = Float80(arc4random64) / Float80(UInt64.max)
Es óptimo para:
Double
(oFloat64
) que tiene una precisión significativa de 52 bits para su mantisaFloat80
que tiene una precisión significativa de 64 bits para su mantisaNotas
Comparaciones con otros métodos
Las respuestas en las que el rango excluye uno de los límites (0 o 1) probablemente adolecen de un sesgo de uniformidad y deben evitarse.
arc4random()
, la mejor precisión es 1 / 0xFFFFFFFF (UINT32_MAX)arc4random_uniform()
, la mejor precisión es 1 / 0xFFFFFFFE (UINT32_MAX-1)rand()
( usando secretamente arc4random ), la mejor precisión es 1 / 0x7FFFFFFF (RAND_MAX)random()
( usando secretamente arc4random ), la mejor precisión es 1 / 0x7FFFFFFF (RAND_MAX)Es matemáticamente imposible de lograr mejor que 32 bits de precisión con una sola llamada a
arc4random
,arc4random_uniform
,rand
orandom
. Por lo tanto, nuestras soluciones anteriores de 32 bits y 64 bits deberían ser las mejores que podamos lograr.fuente
Esta función también funciona para rangos de flotación negativos:
float randomFloat(float Min, float Max){ return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min; }
fuente
Min+(Max-Min)*((float)arc4random())/ULONG_MAX
en su lugar. El(float)
elenco es solo paranoia.Swift 4.2+
Swift 4.2 agrega soporte nativo para un valor aleatorio en un rango:
let x = Float.random(in: 0.0...1.0) let y = Double.random(in: 0.0...1.0) let z = Float80.random(in: 0.0...1.0)
Doc:
random(in range: ClosedRange<Float>)
random(in range: Range<Float>)
random(in range: ClosedRange<Double>)
random(in range: Range<Double>)
random(in range: ClosedRange<Float80>)
random(in range: Range<Float80>)
fuente
(float)rand() / RAND_MAX
La publicación anterior que decía "rand ()" solo era incorrecta. Esta es la forma correcta de usar rand ().
Esto creará un número entre 0 -> 1
fuente
Esta es la extensión para Float número aleatorio Swift 3.1
// MARK: Float Extension public extension Float { /// Returns a random floating point number between 0.0 and 1.0, inclusive. public static var random: Float { return Float(arc4random()) / Float(UInt32.max)) } /// Random float between 0 and n-1. /// /// - Parameter n: Interval max /// - Returns: Returns a random float point number between 0 and n max public static func random(min: Float, max: Float) -> Float { return Float.random * (max - min) + min } }
fuente
Rápido 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 )
let intBetween0to9 = Int.random(in: 0...9) let doubleBetween0to1 = Double.random(in: 0...1)
Todos los tipos de números tienen la función aleatoria estática (en :) que toma el rango y devuelve el número aleatorio en el rango dado.
fuente
Use esto para evitar problemas con el límite superior de arc4random ()
u_int32_t upper_bound = 1000000; float r = arc4random_uniform(upper_bound)*1.0/upper_bound;
Tenga en cuenta que es aplicable para MAC_10_7, IPHONE_4_3 y superior.
fuente
upper_bound-1
. Sin embargo, todavía tendría una precisión arbitrariamente baja causada por upper_bound, por lo que debería aumentar el upper_bound a UINT32_MAX. Y puede obtener una precisión aún mayor al usar enarc4random()*1.0 / UINT32_MAX
lugar dearc4random_uniform(UINT32_MAX)*1.0 / (UINT32_MAX-1)
.arc4random
tiene un rango de hasta 0x100000000 (4294967296)Esta es otra buena opción para generar números aleatorios entre 0 y 1:
srand48(time(0)); // pseudo-random number initializer. double r = drand48();
fuente
float x = arc4random() % 11 * 0.1;
Eso produce un flotador aleatorio entre 0 y 1. Más información aquí
fuente
por defecto produce un número aleatorio (flotante) entre 0 y 1.
fuente
rand()
no parece existir en iOS , y si lo hiciera, produciría un número entero como lo hace en cualquier otro * NIX.rand()
es parte de C, que a su vez es parte de Objective-C (que se usa en la programación de iOS). Las funciones de C comorand()
absolutamente existen en iOS, peroarc4random()
se prefiere.