J'essaie de générer un nombre aléatoire compris entre 0 et 1. Je continue à lire arc4random()
, mais il n'y a aucune information sur l'obtention d'un flottant. Comment puis-je faire cela?
J'essaie de générer un nombre aléatoire compris entre 0 et 1. Je continue à lire arc4random()
, mais il n'y a aucune information sur l'obtention d'un flottant. Comment puis-je faire cela?
Réponses:
Valeur aléatoire dans [0, 1 [ (y compris 0, sauf 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.
ARC4RANDOM_MAX
doit être défini manuellement, mais 0x100000000
c'est 4294967296 , ce qui l'est ULONG_MAX + 1
. Où est-il documenté que arc4random()
le maximum est de ULONG_MAX
toute façon?
// 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, à virgule flottante, uniformément réparties sur l'intervalle [0,0, 1,0].
drand48
faut initialiser une fois avec une graine. La documentation Apple suggère également qu'il devrait être initialisé.
double
. Consultez stackoverflow.com/a/34765674/1033581 pour savoir comment obtenir la meilleure précision.
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 dans [0, 1] (y compris 0.0 et 1.0), précision jusqu'à 32 bits:
Obj-C :
float val = (float)arc4random() / UINT32_MAX;
Swift :
let val = Float(arc4random()) / Float(UInt32.max)
C'est optimal pour:
Float
(ou Float32
) qui a une précision de significande 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 d'amorçage et aussi parce qu'il n'est pas optimal pour randomiser les 52 bits de la double mantisse.
Valeur aléatoire uniforme en [0, 1] , précision de 48 bits:
Swift :
// seed (only needed once)
srand48(Int(Date.timeIntervalSinceReferenceDate))
// random Double value
let val = drand48()
Double
et Float80
)Valeur aléatoire uniforme dans [0, 1] (y compris 0.0 et 1.0), précision jusqu'à 64 bits:
Swift , utilisant deux appels à arc4random:
let arc4random64 = UInt64(arc4random()) << 32 &+ UInt64(arc4random())
let val = Float80(arc4random64) / Float80(UInt64.max)
Swift , en utilisant un appel à arc4random_buf:
var arc4random64: UInt64 = 0
arc4random_buf(&arc4random64, MemoryLayout.size(ofValue: arc4random64))
let val = Float80(arc4random64) / Float80(UInt64.max)
C'est optimal pour:
Double
(ou Float64
) qui a une précision de significande de 52 bits pour sa mantisseFloat80
qui a une précision significand de 64 bits pour sa mantisseLes réponses dans lesquelles la fourchette exclut l'une des bornes (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()
( secrètement en utilisant arc4random ), la meilleure précision est 1 / 0x7FFFFFFF (RAND_MAX)random()
( secrètement en utilisant arc4random ), la meilleure précision est 1 / 0x7FFFFFFF (RAND_MAX)Il est mathématiquement impossible d'obtenir mieux que 32 bits de précision avec un seul appel à arc4random
, arc4random_uniform
, rand
ou random
. Ainsi, nos solutions 32 bits et 64 bits ci-dessus devraient être les meilleures que nous puissions réaliser.
Cette fonction fonctionne également pour les plages de flotteurs négatifs:
float randomFloat(float Min, float Max){
return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}
Min+(Max-Min)*((float)arc4random())/ULONG_MAX
place. Le (float)
casting est juste de la paranoïa.
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:
(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 la
plage de 0 à RAND_MAX (comme défini par le fichier d'en-tête "stdlib.h").
Ceci est une extension pour le nombre aléatoire flottant 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
}
}
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 (in :) qui prend la plage et renvoie le nombre aléatoire dans la plage donnée.
Utilisez ceci pour éviter les problèmes avec la limite supérieure d' 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.
upper_bound-1
. Cependant, vous auriez toujours une précision arbitrairement basse causée par upper_bound, vous devez donc augmenter la valeur upper_bound à UINT32_MAX. Et vous pouvez obtenir une précision encore meilleure en utilisant arc4random()*1.0 / UINT32_MAX
au lieu de arc4random_uniform(UINT32_MAX)*1.0 / (UINT32_MAX-1)
.
arc4random
a une plage allant jusqu'à 0x100000000 (4294967296)
C'est une autre bonne option pour générer des nombres aléatoires entre 0 et 1:
srand48(time(0)); // pseudo-random number initializer.
double r = drand48();
float x = arc4random() % 11 * 0.1;
Cela produit un flottant aléatoire entre 0 et 1. Plus d'informations ici
rand()
par défaut produit un nombre aléatoire (float) entre 0 et 1.
rand()
ne semble pas exister sur iOS , et si c'était le cas, il produirait un entier comme sur tous les autres * NIX.
rand()
fait partie de C, qui fait à son tour partie d'Objective-C (qui est utilisé dans la programmation iOS). Les fonctions C comme rand()
existent absolument sur iOS, mais elles arc4random()
sont préférées.