J'essaie de générer un nombre aléatoire compris entre 0 et 1. Je continue de lire à propos de arc4random()
, mais il n'y a aucune information pour en obtenir un flottant. Comment puis-je faire cela?
Valeur aléatoire dans [0, 1 [ (y compris 0, à l'exclusion de 1):
double val = ((double)arc4random() / UINT32_MAX);
Un peu plus de détails ici .
La plage réelle est [0, 0,999999999767169356] , car la limite supérieure est (double) 0xFFFFFFFF/0x100000000.
// Seed (only once)
srand48(time(0));
double x = drand48();
// Swift version
// Seed (only once)
srand48(Int(Date().timeIntervalSince1970))
let x = drand48()
Les fonctions drand48 () et erand48 () renvoient des valeurs non négatives, à double précision, en virgule flottante, réparties uniformément sur l'intervalle [0,0, 1,0].
Pour Swift 4.2+ voir: https://stackoverflow.com/a/50733095/1033581
Vous trouverez ci-dessous des recommandations pour une uniformité correcte et une précision optimale pour ObjC et Swift 4.1.
Float
)Valeur aléatoire uniforme en [0, 1] (y compris 0,0 et 1,0), jusqu'à 32 bits de précision:
Obj-C :
float val = (float)arc4random() / UINT32_MAX;
Rapide :
let val = Float(arc4random()) / Float(UInt32.max)
Il est optimal pour:
Float
(ou Float32
) qui a une précision significative de 24 bits pour sa mantisseIl est facile d'obtenir une précision de 48 bits avec drand48
( qui utilise arc4random_buf
Sous le capot ). Mais notez que drand48 a des défauts en raison de l'exigence de graine et également d'être sous-optimal pour randomiser les 52 bits de la double mantisse.
Valeur aléatoire uniforme dans [0, 1] , précision 48 bits:
Rapide :
// seed (only needed once)
srand48(Int(Date.timeIntervalSinceReferenceDate))
// random Double value
let val = drand48()
Double
et Float80
)Valeur aléatoire uniforme en [0, 1] (y compris 0,0 et 1,0), jusqu'à 64 bits de précision:
Swift , en utilisant deux appels à arc4random:
let arc4random64 = UInt64(arc4random()) << 32 &+ UInt64(arc4random())
let val = Float80(arc4random64) / Float80(UInt64.max)
Swift , en utilisant un seul appel à arc4random_buf:
var arc4random64: UInt64 = 0
arc4random_buf(&arc4random64, MemoryLayout.size(ofValue: arc4random64))
let val = Float80(arc4random64) / Float80(UInt64.max)
Il est optimal pour:
Double
(ou Float64
) qui a une précision significative de 52 bits pour sa mantisseFloat80
qui a une précision significative de 64 bits pour sa mantisseLes réponses où la plage exclut l'une des limites (0 ou 1) souffrent probablement d'un biais d'uniformité et doivent être évitées.
arc4random()
, la meilleure précision est 1/0xFFFFFFFF (UINT32_MAX)arc4random_uniform()
, la meilleure précision est 1/0xFFFFFFFE (UINT32_MAX-1)Rand()
( en utilisant secrètement arc4random ), la meilleure précision est 1/0x7FFFFFFF (Rand_MAX)random()
( en utilisant secrètement arc4random ), la meilleure précision est 1/0x7FFFFFFF (Rand_MAX)Il est mathématiquement impossible d'obtenir une précision supérieure à 32 bits avec un seul appel à arc4random
, arc4random_uniform
, Rand
ou random
. Nos solutions ci-dessus 32 bits et 64 bits devraient donc être les meilleures que nous puissions atteindre.
Cette fonction fonctionne également pour les plages de flottement négatives:
float randomFloat(float Min, float Max){
return ((arc4random()%Rand_MAX)/(Rand_MAX*1.0))*(Max-Min)+Min;
}
Swift 4.2 ajoute la prise en charge native d'une valeur aléatoire dans une plage:
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:
Swift 4.2
Swift 4.2 a inclus une API de nombres aléatoires native et assez complète dans la bibliothèque standard. ( proposition Swift Evolution SE-0202 )
let intBetween0to9 = Int.random(in: 0...9)
let doubleBetween0to1 = Double.random(in: 0...1)
Tous les types de nombres ont la fonction statique aléatoire (dans:) qui prend la plage et renvoie le nombre aléatoire dans la plage donnée.
(float)Rand() / Rand_MAX
Le message précédent indiquant "Rand ()" seul était incorrect. C'est la bonne façon d'utiliser Rand ().
Cela créera un nombre entre 0 -> 1
Documents BSD:
La fonction Rand () calcule une séquence d'entiers pseudo-aléatoires dans le
plage de 0 à Rand_MAX (tel que défini par le fichier d'en-tête "stdlib.h").
Ceci est l'extension pour Float random number 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
}
}
Utilisez ceci pour éviter les problèmes avec la limite supérieure de arc4random ()
u_int32_t upper_bound = 1000000;
float r = arc4random_uniform(upper_bound)*1.0/upper_bound;
Notez qu'il est applicable pour MAC_10_7, IPHONE_4_3 et supérieur.