Estoy tratando de generar un número aleatorio entre 0 y 1. Sigo leyendo sobre arc4random()
, pero no hay información sobre cómo obtener un flotador de él. ¿Cómo hago esto?
Genera un flotante aleatorio entre 0 y 1
jini
vladimir
Valor aleatorio en [0, 1[ (including 0, excluding 1):
double val = ((double)arc4random() / UINT32_MAX);
A bit more details here.
Actual range is [0, 0.999999999767169356]como límite superior es (doble) 0xFFFFFFFF / 0x100000000.
-
Gracias. La respuesta más directa que he visto. Leeré su enlace y obtendré detalles adicionales sobre esto. Gracias de nuevo.
– jini
2 de marzo de 2011 a las 19:40
-
es raro que
ARC4RANDOM_MAX
debe definirse manualmente, pero0x100000000
es 4294967296cual esULONG_MAX + 1
. ¿Dónde está documentado quearc4random()
el máximo de esULONG_MAX
¿de todos modos?– bobobobo
15/09/2012 a las 16:53
-
@bobobobo, desde aquí: desarrollador.apple.com/library/mac/#documentation/Darwin/Reference/… La función arc4random() devuelve números pseudoaleatorios en el rango de 0 a (2**32)-1
– Vladímir
15 de septiembre de 2012 a las 17:18
-
En realidad, el valor debería ser 0xFFFFFFFF, (2**32)-1 == 0x100000000 – 0x1 == 0xFFFFFFFF == UINT32_MAX como lo indica actualmente Jörg Bühmann en el enlace.
– Josejulio
10 de diciembre de 2014 a las 16:51
-
¡No se garantiza que los valores generados de esta manera se distribuyan uniformemente!
– Kelin
9 de junio de 2015 a las 8:05
jovan stankovic
// Seed (only once)
srand48(time(0));
double x = drand48();
// Swift version
// Seed (only once)
srand48(Int(Date().timeIntervalSince1970))
let x = drand48()
Las funciones drand48() y erand48() devuelven valores de punto flotante no negativos, de doble precisión, distribuidos uniformemente en el intervalo [0.0 , 1.0].
-
Esta debería ser la mejor respuesta.
– John Riselvato
22 ago 2013 a las 14:00
-
Tal vez necesites actualizar un poco la respuesta, yo leer en NSHipster que
drand48
necesita ser inicializado una vez con una semilla. los documentación de manzana También sugiero que debe ser inicializado.– dulaccc
02/09/2014 a las 13:39
-
La semilla es necesaria porque le da a este generador aleatorio un punto de partida para los cálculos. Sin ella, la secuencia aleatoria siempre sería la misma en todos los lanzamientos de aplicaciones.
– Jovan Stankovic
4 de febrero de 2017 a las 13:52
-
Esta es la mejor respuesta.
– sabialandia
26 de mayo de 2017 a las 10:42
-
Esta respuesta no es una respuesta de precisión óptima para un
double
. Consulte stackoverflow.com/a/34765674/1033581 sobre cómo lograr la mejor precisión.– Corazón
21 de marzo de 2018 a las 1:31
Coeur
Para Swift 4.2+ ver: https://stackoverflow.com/a/50733095/1033581
A continuación, se incluyen recomendaciones para lograr 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] (incluyendo 0.0 y 1.0), hasta 32 bits de precisión:
Obj-C:
float val = (float)arc4random() / UINT32_MAX;
Rápido:
let val = Float(arc4random()) / Float(UInt32.max)
Es óptimo para:
- a
Float
(oFloat32
) que tiene una precisión significativa de 24 bits para su mantisa
Precisión de 48 bits (desaconsejada)
Es fácil lograr una precisión de 48 bits con drand48
(que utiliza arc4random_buf
bajo el capó). Pero ten en cuenta que drand48 tiene defectos debido al requisito de semilla y también por ser subóptimo para aleatorizar los 52 bits de Double mantissa.
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
y Float80
)
Valor aleatorio uniforme en [0, 1] (incluyendo 0.0 y 1.0), hasta 64 bits de precisión:
Rápidousando dos llamadas a arc4random:
let arc4random64 = UInt64(arc4random()) << 32 &+ UInt64(arc4random())
let val = Float80(arc4random64) / Float80(UInt64.max)
Rápidousando 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:
- a
Double
(oFloat64
) que tiene una precisión significativa de 52 bits para su mantisa - a
Float80
que tiene una precisión significativa de 64 bits para su mantisa
notas
Comparaciones con otros métodos
Las respuestas donde el rango excluye uno de los límites (0 o 1) probablemente sufran un sesgo de uniformidad y deben evitarse.
- utilizando
arc4random()
la mejor precisión es 1/0xFFFFFFFF (UINT32_MAX) - utilizando
arc4random_uniform()
la mejor precisión es 1/0xFFFFFFFE (UINT32_MAX-1) - utilizando
rand()
(secretamente usando arc4random), la mejor precisión es 1 / 0x7FFFFFFF (RAND_MAX) - utilizando
random()
(secretamente usando arc4random), la mejor precisión es 1 / 0x7FFFFFFF (RAND_MAX)
Es matemáticamente imposible lograr una precisión superior a 32 bits con una sola llamada a arc4random
, arc4random_uniform
, rand
o random
. Por lo tanto, nuestras soluciones anteriores de 32 bits y 64 bits deberían ser las mejores que podamos lograr.
-
‘Float80’ no está disponible en dispositivos iOS reales (solo funciona en simulador).
– Corazón
29 de noviembre de 2018 a las 9:14
Esta función también funciona para rangos flotantes negativos:
float randomFloat(float Min, float Max){
return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}
Coeur
Rápido 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:
Frungi
(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
Documentos BSD:
La función rand() calcula una secuencia de enteros pseudoaleatorios en el
rango de 0 a RAND_MAX (como se define en el archivo de encabezado “stdlib.h”).
Esta es la extensión para el número aleatorio flotante Rápido 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
}
}
-
@Cœur Gracias, lo cambio.
– Yann Steph
27/09/2017 a las 20:11
No duplicados, esta parece ser la única pregunta explícitamente relacionada con los flotadores.
– Pi
29 de mayo de 2011 a las 8:56