Generate a random float between 0 and 1

62,093

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 (or Float32) 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 (or Float64) 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:

Share:
62,093

Related videos on Youtube

jini
Author by

jini

Updated on June 14, 2020

Comments

  • jini
    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
      P i almost 13 years
      Not duplicates, this appears to be the only question explicitly pertaining to floats.
  • jini
    jini about 13 years
    Thank You. Most straight forward answer I have seen. I will read up on your link and get additional details on this. Thanks again.
  • TalkLittle
    TalkLittle over 11 years
    Note: only gives 11 discrete values: 0.0, 0.1, 0.2, ..., 1.0
  • bobobobo
    bobobobo over 11 years
    Yes, 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
    bobobobo over 11 years
    It's weird that ARC4RANDOM_MAX has to be manually defined, but 0x100000000 is 4294967296, which is ULONG_MAX + 1. Where is it documented that arc4random()'s max is ULONG_MAX anyhow?
  • Vladimir
    Vladimir over 11 years
    @bobobobo, from here: developer.apple.com/library/mac/#documentation/Darwin/Refere‌​nce/… The arc4random() function returns pseudo-random numbers in the range of 0 to (2**32)-1
  • Vladimir
    Vladimir over 11 years
    @bobobobo, although I agree that defining constant for this case does not look nice
  • bobobobo
    bobobobo over 11 years
    Extraneous modulus operation. use Min+(Max-Min)*((float)arc4random())/ULONG_MAX instead. The (float) cast is just paranoia.
  • AlexQueue
    AlexQueue over 11 years
    This produces a random int for me.
  • jscs
    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
    John Riselvato almost 11 years
    This should be the best answer.
  • Frungi
    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 like rand() absolutely exist on iOS, but arc4random() is preferred.
  • dulaccc
    dulaccc over 9 years
    You 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
    Josejulio over 9 years
    Actually, 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
    Iulian Onofrei almost 9 years
    @Vladimir, What type is ARC4RANDOM_MAX? I want to define it as a variable.
  • Vladimir
    Vladimir almost 9 years
    @IulianOnofrei, you can declare it as unsigned long.
  • kelin
    kelin almost 9 years
    Values generated such a way are not guaranteed to be uniformly distributed!
  • Cœur
    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
    Jovan Stankovic over 7 years
    Seed 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
    sabiland almost 7 years
    This IS the best answer.
  • Cœur
    Cœur over 6 years
    arc4random max value is 0xFFFFFFFF
  • Gurunatha Dogi
    Gurunatha Dogi over 6 years
    Thanks @Cœur ..max val 0xFFFFFFFF i wasn't know
  • Cœur
    Cœur over 6 years
    There 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 using arc4random()*1.0 / UINT32_MAX instead of arc4random_uniform(UINT32_MAX)*1.0 / (UINT32_MAX-1).
  • Cœur
    Cœur over 6 years
    your solution is also identical to Jovan Stankovic answer.
  • Gurunatha Dogi
    Gurunatha Dogi over 6 years
    Ohh i didn't saw that @Cœur
  • YannSteph
    YannSteph over 6 years
    @Cœur Thanks you i change that
  • Cœur
    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
    Cœur about 6 years
    This answer is not an optimal precision answer for a double. See stackoverflow.com/a/34765674/1033581 on how to achieve best precision.
  • Cœur
    Cœur over 5 years
    'Float80' is unavailable on real iOS devices (it only works on simulator).