Generate a random float between 0 and 1
Solution 1
Random value in [0, 1[ (including 0, excluding 1):
double val = ((double)arc4random() / UINT32_MAX);
A bit more details here.
Actual range is [0, 0.999999999767169356], as upper bound is (double)0xFFFFFFFF / 0x100000000.
Solution 2
// Seed (only once)
srand48(time(0));
double x = drand48();
// Swift version
// Seed (only once)
srand48(Int(Date().timeIntervalSince1970))
let x = drand48()
The drand48() and erand48() functions return non-negative, double-precision, floating-point values, uniformly distributed over the interval [0.0 , 1.0].
Solution 3
For Swift 4.2+ see: https://stackoverflow.com/a/50733095/1033581
Below are recommendations for correct uniformity and optimal precision for ObjC and Swift 4.1.
32 bits precision (Optimal for Float
)
Uniform random value in [0, 1] (including 0.0 and 1.0), up to 32 bits precision:
Obj-C:
float val = (float)arc4random() / UINT32_MAX;
Swift:
let val = Float(arc4random()) / Float(UInt32.max)
It's optimal for:
- a
Float
(orFloat32
) which has a significand precision of 24 bits for its mantissa
48 bits precision (discouraged)
It's easy to achieve 48 bits precision with drand48
(which uses arc4random_buf
under the hood). But note that drand48 has flaws because of the seed requirement and also for being suboptimal to randomize all 52 bits of Double mantissa.
Uniform random value in [0, 1], 48 bits precision:
Swift:
// seed (only needed once)
srand48(Int(Date.timeIntervalSinceReferenceDate))
// random Double value
let val = drand48()
64 bits precision (Optimal for Double
and Float80
)
Uniform random value in [0, 1] (including 0.0 and 1.0), up to 64 bits precision:
Swift, using two calls to arc4random:
let arc4random64 = UInt64(arc4random()) << 32 &+ UInt64(arc4random())
let val = Float80(arc4random64) / Float80(UInt64.max)
Swift, using one call to arc4random_buf:
var arc4random64: UInt64 = 0
arc4random_buf(&arc4random64, MemoryLayout.size(ofValue: arc4random64))
let val = Float80(arc4random64) / Float80(UInt64.max)
It's optimal for:
- a
Double
(orFloat64
) which has a significand precision of 52 bits for its mantissa - a
Float80
which has a significand precision of 64 bits for its mantissa
Notes
Comparisons with other methods
Answers where the range is excluding one of the bounds (0 or 1) likely suffer from a uniformity bias and should be avoided.
- using
arc4random()
, best precision is 1 / 0xFFFFFFFF (UINT32_MAX) - using
arc4random_uniform()
, best precision is 1 / 0xFFFFFFFE (UINT32_MAX-1) - using
rand()
(secretly using arc4random), best precision is 1 / 0x7FFFFFFF (RAND_MAX) - using
random()
(secretly using arc4random), best precision is 1 / 0x7FFFFFFF (RAND_MAX)
It's mathematically impossible to achieve better than 32 bits precision with a single call to arc4random
, arc4random_uniform
, rand
or random
. So our above 32 bits and 64 bits solutions should be the best we can achieve.
Solution 4
This function works for negative float ranges as well:
float randomFloat(float Min, float Max){
return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}
Solution 5
Swift 4.2+
Swift 4.2 adds native support for a random value in a Range:
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:
Related videos on Youtube
jini
Updated on June 14, 2020Comments
-
jini almost 4 years
I'm trying to generate a random number that's between 0 and 1. I keep reading about
arc4random()
, but there isn't any information about getting a float from it. How do I do this?-
P i almost 13 yearsNot duplicates, this appears to be the only question explicitly pertaining to floats.
-
-
jini about 13 yearsThank You. Most straight forward answer I have seen. I will read up on your link and get additional details on this. Thanks again.
-
TalkLittle over 11 yearsNote: only gives 11 discrete values: 0.0, 0.1, 0.2, ..., 1.0
-
bobobobo over 11 yearsYes, the modulus operation cuts arc4random()'s result to being between 0 and 10, then he divides it by 10. This answer is really bad for general use.
-
bobobobo over 11 yearsIt's weird that
ARC4RANDOM_MAX
has to be manually defined, but0x100000000
is 4294967296, which isULONG_MAX + 1
. Where is it documented thatarc4random()
's max isULONG_MAX
anyhow? -
Vladimir over 11 years@bobobobo, from here: developer.apple.com/library/mac/#documentation/Darwin/Reference/… The arc4random() function returns pseudo-random numbers in the range of 0 to (2**32)-1
-
Vladimir over 11 years@bobobobo, although I agree that defining constant for this case does not look nice
-
bobobobo over 11 yearsExtraneous modulus operation. use
Min+(Max-Min)*((float)arc4random())/ULONG_MAX
instead. The(float)
cast is just paranoia. -
AlexQueue over 11 yearsThis produces a random int for me.
-
jscs about 11 years
rand()
doesn't seem to exist on iOS, and if it did, it would produce an integer like it does on every other *NIX. -
John Riselvato almost 11 yearsThis should be the best answer.
-
Frungi over 10 years@JoshCaswell
rand()
is part of C, which is in turn part of Objective-C (which is used in iOS programming). C functions likerand()
absolutely exist on iOS, butarc4random()
is preferred. -
dulaccc over 9 yearsYou maybe need to update just a little the answer, I read on NSHipster that
drand48
need to be initialized once with a seed. The Apple documentation also suggest that it should be initialized. -
Josejulio over 9 yearsActually, the value should be 0xFFFFFFFF, (2**32)-1 == 0x100000000 - 0x1 == 0xFFFFFFFF == UINT32_MAX as currently stated by Jörg Bühmann on the link.
-
Iulian Onofrei almost 9 years@Vladimir, What type is
ARC4RANDOM_MAX
? I want to define it as a variable. -
Vladimir almost 9 years@IulianOnofrei, you can declare it as unsigned long.
-
kelin almost 9 yearsValues generated such a way are not guaranteed to be uniformly distributed!
-
Cœur over 8 years@Josejulio, you're right, I've made a separate answer using
UINT32_MAX
: stackoverflow.com/a/34765674/1033581 -
Jovan Stankovic over 7 yearsSeed is needed because it gives this random generator a starting point for calculations. Without it random sequence would always be the same across app launches.
-
sabiland almost 7 yearsThis IS the best answer.
-
Cœur over 6 yearsarc4random max value is 0xFFFFFFFF
-
Gurunatha Dogi over 6 yearsThanks @Cœur ..max val 0xFFFFFFFF i wasn't know
-
Cœur over 6 yearsThere is a fundamental range issue with this. It's easily noticeable when you set upper_bound to 10, arc4random_uniform will return values from 0 to 9, and final result will be from 0.0000 to 0.9000. You should instead divide by
upper_bound-1
. Yet, you would still have an arbitrarily low precision caused by upper_bound, so you should increase the upper_bound to UINT32_MAX. And you can get even better precision from usingarc4random()*1.0 / UINT32_MAX
instead ofarc4random_uniform(UINT32_MAX)*1.0 / (UINT32_MAX-1)
. -
Cœur over 6 yearsyour solution is also identical to Jovan Stankovic answer.
-
Gurunatha Dogi over 6 yearsOhh i didn't saw that @Cœur
-
YannSteph over 6 years@Cœur Thanks you i change that
-
Cœur about 6 years@bobobobo while I agree on the extraneous modulus, I advice to divide by UINT32_MAX (4294967295 always) instead of ULONG_MAX (18446744073709551615 on 64 bits).
-
Cœur about 6 yearsThis answer is not an optimal precision answer for a
double
. See stackoverflow.com/a/34765674/1033581 on how to achieve best precision. -
Cœur over 5 years'Float80' is unavailable on real iOS devices (it only works on simulator).