Генерация случайного числа с плавающей точкой от 0 до 1 - PullRequest
82 голосов
/ 02 марта 2011

Я пытаюсь сгенерировать случайное число, которое находится между 0 и 1. Я продолжаю читать о arc4random(), но нет никакой информации о том, как получить число с плавающей точкой. Как мне это сделать?

Ответы [ 13 ]

134 голосов
/ 02 марта 2011

Случайное значение в [0, 1 [ (включая 0, исключая 1):

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

Немного подробнее здесь .

Фактический диапазон: [0, 0.999999999767169356] , поскольку верхняя граница (двойная) 0xFFFFFFFF / 0x100000000.

105 голосов
/ 05 июня 2013
// Seed (only once)
srand48(time(0));

double x = drand48();

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

let x = drand48()

Функции drand48 () и erand48 () возвращают неотрицательные значения двойной точности с плавающей запятой, равномерно распределенные по интервалу [0.0, 1.0].

14 голосов
/ 13 января 2016

Для Swift 4.2+ см .: https://stackoverflow.com/a/50733095/1033581


Ниже приведены рекомендации по правильной однородности и оптимальной точности для ObjC и Swift 4.1.

32-битная точность (оптимально для Float)

Унифицированное случайное значение в [0, 1] (включая 0,0 и 1,0) с точностью до 32 бит:

Obj-C

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

Swift :

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

Оптимально для:

  • a Float (или Float32), который имеет значимость и точность 24 бит для своей мантиссы

Точность 48 бит (не рекомендуется)

С помощью drand48 (, который использует arc4random_buf под капотом ) легко достичь точности 48 бит. Но обратите внимание, что drand48 имеет недостатки из-за потребности в семени, а также из-за того, что он неоптимален для рандомизации всех 52 битов двойной мантиссы.

Равномерное случайное значение в [0, 1] , точность 48 бит:

Swift

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

64-битная точность (оптимально для Double и Float80)

Унифицированное случайное значение в [0, 1] (включая 0,0 и 1,0) с точностью до 64 бит:

Swift , используя два вызова arc4random:

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

Swift , используя один вызов arc4random_buf:

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

Оптимально для:

  • a Double (или Float64), который имеет значимость и точность 52 бит для своей мантиссы
  • a Float80, который имеет значимость и точность 64 бит для своей мантиссы

Примечания

Сравнение с другими методами

Ответы, где диапазон исключает одну из границ (0 или 1), вероятно, страдают от систематической ошибки и их следует избегать.

  • с использованием arc4random(), наилучшая точность составляет 1 / 0xFFFFFFFF (UINT32_MAX)
  • с использованием arc4random_uniform(), лучшая точность 1 / 0xFFFFFFFE (UINT32_MAX-1)
  • с использованием rand() ( тайно с использованием arc4random ), наилучшая точность составляет 1 / 0x7FFFFFFF (RAND_MAX)
  • с использованием random() ( тайно с использованием arc4random ), наилучшая точность составляет 1 / 0x7FFFFFFF (RAND_MAX)

С математической точки зрения невозможно достичь лучшей точности, чем 32-битная, с помощью одного вызова arc4random, arc4random_uniform, rand или random. Поэтому наши вышеупомянутые 32-битные и 64-битные решения должны быть лучшими, которые мы можем достичь.

10 голосов
/ 03 мая 2012

Эта функция работает и для отрицательных диапазонов:

float randomFloat(float Min, float Max){
    return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}
4 голосов
/ 07 июня 2018

Swift 4.2 +

Swift 4.2 добавляет встроенную поддержку для случайного значения в диапазоне:

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)

Док:

1 голос
/ 10 июня 2018

Swift 4.2

Swift 4.2 включил собственный и довольно полнофункциональный API случайных чисел в стандартную библиотеку.( Предложение Swift Evolution SE-0202 )

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

Все типы чисел имеют статическую функцию random (in:) , которая принимает диапазон и возвращает случайное числов заданном диапазоне.

1 голос
/ 06 сентября 2017

Это расширение для случайного числа с плавающей точкой 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 голос
/ 31 января 2013
(float)rand() / RAND_MAX

Предыдущее сообщение о том, что «rand ()» было неверно. Это правильный способ использования rand ().

Это создаст число от 0 до> 1

BSD документы:

Функция rand () вычисляет последовательность псевдослучайных чисел в
диапазон от 0 до RAND_MAX (как определено в заголовочном файле "stdlib.h").

0 голосов
/ 27 сентября 2017

arc4random имеет диапазон до 0x100000000 (4294967296)

Это еще один хороший вариант для генерации случайных чисел от 0 до 1:

srand48(time(0));      // pseudo-random number initializer.
double r = drand48();
0 голосов
/ 28 февраля 2014

Используйте это, чтобы избежать проблем с верхней границей arc4random ()

u_int32_t upper_bound = 1000000;

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

Обратите внимание, что это применимо для MAC_10_7, IPHONE_4_3 и выше.

...