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?
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.
ARC4RANDOM_MAX
tenga que definirse manualmente, pero 0x100000000
es 4294967296 , que es ULONG_MAX + 1
. ¿Dónde está documentado que arc4random()
es máximo de ULONG_MAX
todos modos?
// 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 coma flotante no negativos, de doble precisión, distribuidos uniformemente en el intervalo [0.0, 1.0].
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.
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 :
let val = Float(arc4random()) / Float(UInt32.max)
Es óptimo para:
Float
(o Float32
) que tiene una precisión significativa de 24 bits para su mantisaEs fácil lograr una precisión de 48 bits con drand48
( que se usa arc4random_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()
Double
y Float80
)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
(o Float64
) que tiene una precisión significativa de 52 bits para su mantisaFloat80
que tiene una precisión significativa de 64 bits para su mantisaLas 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
o random
. Por lo tanto, nuestras soluciones anteriores de 32 bits y 64 bits deberían ser las mejores que podamos lograr.
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;
}
Min+(Max-Min)*((float)arc4random())/ULONG_MAX
en su lugar. El (float)
elenco es solo paranoia.
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:
(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 lo define el archivo de encabezado "stdlib.h").
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
}
}
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.
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.
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 en arc4random()*1.0 / UINT32_MAX
lugar de arc4random_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();
float x = arc4random() % 11 * 0.1;
Eso produce un flotador aleatorio entre 0 y 1. Más información aquí
rand()
por defecto produce un número aleatorio (flotante) entre 0 y 1.
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 como rand()
absolutamente existen en iOS, pero arc4random()
se prefiere.