web-dev-qa-db-fra.com

Génère un flottant aléatoire entre 0 et 1

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?

82
jini

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.

134
Vladimir
// 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].

105
Jovan Stankovic

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.

Précision 32 bits (optimale pour 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:

  • un Float (ou Float32) qui a une précision significative de 24 bits pour sa mantisse

Précision de 48 bits (déconseillé)

Il 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()

Précision 64 bits (optimal pour 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:

  • un Double (ou Float64) qui a une précision significative de 52 bits pour sa mantisse
  • un Float80 qui a une précision significative de 64 bits pour sa mantisse

Remarques

Comparaisons avec d'autres méthodes

Les 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.

  • en utilisant arc4random(), la meilleure précision est 1/0xFFFFFFFF (UINT32_MAX)
  • en utilisant arc4random_uniform(), la meilleure précision est 1/0xFFFFFFFE (UINT32_MAX-1)
  • en utilisant Rand() ( en utilisant secrètement arc4random ), la meilleure précision est 1/0x7FFFFFFF (Rand_MAX)
  • en utilisant 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.

15
Cœur

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;
}
10
Héctor Sanchez

Swift 4.2+

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:

4
Cœur

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.

1
Suhit Patil
(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").

1
Leslie Godwin

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
    }
}
1
YannSteph

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.

0
malex