Generieren Sie einen zufälligen Float zwischen 0 und 1


84

Ich versuche , eine Zufallszahl zu erzeugen, ist zwischen 0 und 1. Ich halte das Lesen über arc4random(), aber es gibt keine Informationen über einen Schwimmer von ihm zu bekommen. Wie mache ich das?


1
Keine Duplikate, dies scheint die einzige Frage zu sein, die sich explizit auf Floats bezieht.
P i

Antworten:


138

Zufälliger Wert in [0, 1 [ (einschließlich 0, ohne 1):

double val = ((double)arc4random() / UINT32_MAX);

Ein bisschen mehr Details hier .

Der tatsächliche Bereich ist [0, 0,999999999767169356] , da die Obergrenze (doppelt) 0xFFFFFFFF / 0x100000000 ist.


Danke. Die direkteste Antwort, die ich gesehen habe. Ich werde Ihren Link nachlesen und zusätzliche Details dazu erhalten. Danke noch einmal.
Jini

3
Es ist seltsam , dass ARC4RANDOM_MAXmanuell definiert werden, sondern 0x100000000ist 4294967296 , was ist ULONG_MAX + 1. Wo ist dokumentiert, dass arc4random()das Maximum ULONG_MAXsowieso ist?
Bobobobo

@bobobobo, von hier aus: developer.apple.com/library/mac/#documentation/Darwin/Reference/… Die Funktion arc4random () gibt Pseudozufallszahlen im Bereich von 0 bis (2 ** 32) -1
Vladimir zurück

8
Eigentlich sollte der Wert 0xFFFFFFFF, (2 ** 32) -1 == 0x100000000 - 0x1 == 0xFFFFFFFF == UINT32_MAX sein, wie derzeit von Jörg Bühmann auf dem Link angegeben.
Josejulio

1
Auf diese Weise erzeugte Werte sind nicht garantiert gleichmäßig verteilt!
Kelin

107
// Seed (only once)
srand48(time(0));

double x = drand48();

// Swift version
// Seed (only once)
srand48(Int(Date().timeIntervalSince1970))

let x = drand48()

Die Funktionen drand48 () und erand48 () geben nicht negative Gleitkommawerte mit doppelter Genauigkeit zurück, die gleichmäßig über das Intervall verteilt sind [0.0, 1.0].


19
Dies sollte die beste Antwort sein.
John Riselvato

Möglicherweisedrand48 müssen Sie die Antwort nur ein wenig aktualisieren. Ich habe auf NSHipster gelesen , dass sie einmal mit einem Startwert initialisiert werden muss. Die Apple-Dokumentation schlägt außerdem vor, dass es initialisiert werden sollte.
dulaccc

1
Seed wird benötigt, weil es diesem Zufallsgenerator einen Ausgangspunkt für Berechnungen gibt. Ohne sie wäre die zufällige Reihenfolge bei App-Starts immer gleich.
Jovan Stankovic

Dies ist die beste Antwort.
Sabiland

Diese Antwort ist keine optimale Präzisionsantwort für a double. Informationen zum Erreichen der besten Präzision finden Sie unter stackoverflow.com/a/34765674/1033581 .
Cœur

16

Swift 4.2+ finden Sie unter: https://stackoverflow.com/a/50733095/1033581


Nachfolgend finden Sie Empfehlungen zur korrekten Gleichmäßigkeit und optimalen Präzision für ObjC und Swift 4.1.

32 Bit Genauigkeit (Optimal für Float)

Einheitlicher Zufallswert in [0, 1] (einschließlich 0.0 und 1.0) mit einer Genauigkeit von bis zu 32 Bit:

Obj-C :

float val = (float)arc4random() / UINT32_MAX;

Swift :

let val = Float(arc4random()) / Float(UInt32.max)

Es ist optimal für:

  • ein Float (oder Float32) mit einer signifikanten Genauigkeit von 24 Bit für seine Mantisse

48 Bit Genauigkeit (nicht empfohlen)

Es ist einfach, eine Genauigkeit von 48 Bit zu erreichen drand48( die arc4random_bufunter der Haube verwendet wird ). Aber beachte das drand48 aufgrund der Seed-Anforderung und auch aufgrund der suboptimalen Zufallsgenerierung aller 52 Bits der Doppelmantisse Fehler aufweist .

Einheitlicher Zufallswert in [0, 1] , 48 Bit Genauigkeit:

Swift :

// seed (only needed once)
srand48(Int(Date.timeIntervalSinceReferenceDate))
// random Double value
let val = drand48()

64 Bit Genauigkeit (Optimal für DoubleundFloat80 )

Einheitlicher Zufallswert in [0, 1] (einschließlich 0.0 und 1.0) mit einer Genauigkeit von bis zu 64 Bit:

Swift verwendet zwei Aufrufe von arc4random:

let arc4random64 = UInt64(arc4random()) << 32 &+ UInt64(arc4random())
let val = Float80(arc4random64) / Float80(UInt64.max)

Swift mit einem Aufruf von arc4random_buf:

var arc4random64: UInt64 = 0
arc4random_buf(&arc4random64, MemoryLayout.size(ofValue: arc4random64))
let val = Float80(arc4random64) / Float80(UInt64.max)

Es ist optimal für:

  • a Double(oderFloat64 ) mit einer signifikanten Genauigkeit von 52 Bit für seine Mantisse
  • a Float80mit einer signifikanten Genauigkeit von 64 Bit für seine Mantisse

Anmerkungen

Vergleiche mit anderen Methoden

Antworten, bei denen der Bereich eine der Grenzen (0 oder 1) ausschließt, leiden wahrscheinlich unter einer Gleichmäßigkeitsverzerrung und sollten vermieden werden.

  • unter Verwendung arc4random()ist die beste Genauigkeit 1 / 0xFFFFFFFF (UINT32_MAX)
  • unter Verwendung arc4random_uniform()ist die beste Genauigkeit 1 / 0xFFFFFFFE (UINT32_MAX-1)
  • Mit rand()( heimlich mit arc4random ) ist die beste Genauigkeit 1 / 0x7FFFFFFF (RAND_MAX).
  • Mit random()( heimlich mit arc4random ) ist die beste Genauigkeit 1 / 0x7FFFFFFF (RAND_MAX).

Es ist mathematisch unmöglich besser als 32 - Bit - Präzision mit einem einzigen Anruf zu erzielen arc4random, arc4random_uniform, randoder random. Daher sollten unsere über 32-Bit- und 64-Bit-Lösungen die besten sein, die wir erreichen können.


'Float80' ist auf echten iOS-Geräten nicht verfügbar (funktioniert nur auf dem Simulator).
Cœur

10

Diese Funktion funktioniert auch für negative Float-Bereiche:

float randomFloat(float Min, float Max){
    return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}

4
Fremdmodulbetrieb. Verwenden Sie Min+(Max-Min)*((float)arc4random())/ULONG_MAXstattdessen. Die (float)Besetzung ist nur Paranoia.
Bobobobo

@bobobobo Während ich dem Fremdmodul zustimme, empfehle ich, durch UINT32_MAX (immer 4294967295) anstelle von ULONG_MAX (18446744073709551615 auf 64 Bit) zu teilen.
Cœur


1
(float)rand() / RAND_MAX

Der vorherige Beitrag mit der Angabe "rand ()" war falsch. Dies ist der richtige Weg, um rand () zu verwenden.

Dadurch wird eine Zahl zwischen 0 -> 1 erstellt

BSD-Dokumente:

Die Funktion rand () berechnet eine Folge von pseudozufälligen ganzen Zahlen im
Bereich von 0 bis RAND_MAX (wie in der Header-Datei "stdlib.h" definiert).


1

Dies ist eine Erweiterung für die Float-Zufallszahl 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
    }
}

@ Cœur Danke, ich ändere das
YannSteph

1

Swift 4.2

Swift 4.2 hat eine native und ziemlich voll funktionsfähige Zufallszahlen-API in die Standardbibliothek aufgenommen. ( Swift Evolution Vorschlag SE-0202 )

let intBetween0to9 = Int.random(in: 0...9) 
let doubleBetween0to1 = Double.random(in: 0...1)

Alle Zahlentypen haben die statische Zufallsfunktion (in :) , die den Bereich übernimmt und die Zufallszahl im angegebenen Bereich zurückgibt.


0

Verwenden Sie diese Option , um Probleme mit der Obergrenze von arc4random () zu vermeiden.

u_int32_t upper_bound = 1000000;

float r = arc4random_uniform(upper_bound)*1.0/upper_bound;

Beachten Sie, dass dies für MAC_10_7, IPHONE_4_3 und höher gilt.


Hierbei gibt es ein grundlegendes Problem mit der Reichweite. Wenn Sie Upper_bound auf 10 setzen, fällt dies leicht auf. Arc4random_uniform gibt Werte von 0 bis 9 zurück und das Endergebnis liegt zwischen 0,0000 und 0,9000. Sie sollten stattdessen durch teilen upper_bound-1. Sie hätten jedoch immer noch eine willkürlich niedrige Genauigkeit, die durch Upper_bound verursacht wird. Daher sollten Sie die Upper_bound auf UINT32_MAX erhöhen. Und Sie können noch präziser arbeiten, wenn Sie arc4random()*1.0 / UINT32_MAXstatt verwenden arc4random_uniform(UINT32_MAX)*1.0 / (UINT32_MAX-1).
Cœur

-1

Wie wäre es mit dieser Operation ((CGFloat)(rand()%100)/100)?


Modulo Bias und Precision Bias. Leslie Godwins Antwort ist besser für die gleiche Idee.
Cœur

-1

arc4random hat einen Bereich bis 0x100000000 (4294967296)

Dies ist eine weitere gute Option, um Zufallszahlen zwischen 0 und 1 zu generieren:

srand48(time(0));      // pseudo-random number initializer.
double r = drand48();

arc4random max Wert ist 0xFFFFFFFF
Cœur

Danke @ Cœur ..max val 0xFFFFFFFF Ich wusste es nicht
Gurunatha Dogi

Ihre Lösung ist auch identisch mit der Antwort von Jovan Stankovic.
Cœur

Ohh ich habe das nicht gesehen @ Cœur
Gurunatha Dogi

-4
float x = arc4random() % 11 * 0.1;

Das ergibt einen zufälligen Float zwischen 0 und 1. Mehr Infos hier


3
Hinweis: gibt nur 11 diskrete Werte an: 0.0, 0.1, 0.2, ..., 1.0
TalkLittle

8
Ja, die Moduloperation reduziert das Ergebnis von arc4random () auf 0 bis 10, dann dividiert er es durch 10. Diese Antwort ist für den allgemeinen Gebrauch wirklich schlecht.
Bobobobo

-4
rand() 

Standardmäßig wird eine Zufallszahl (float) zwischen 0 und 1 erzeugt.


4
Dies erzeugt ein zufälliges int für mich.
AlexQueue

rand()scheint unter iOS nicht zu existieren , und wenn dies der Fall wäre, würde es eine Ganzzahl erzeugen, wie es bei jedem anderen * NIX der Fall ist.
Jscs

2
@JoshCaswell rand()ist Teil von C, das wiederum Teil von Objective-C ist (das in der iOS-Programmierung verwendet wird). C-Funktionen wie rand()auf iOS existieren absolut, werden aber arc4random()bevorzugt.
Frungi
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.