Генерирует случайный float между 0 и 1
Я пытаюсь генерировать случайные числа между 0 и 1. Я продолжаю читать о arc4random()
, но нет никакой информации о получении поплавок от него. Как мне это сделать?
13 ответов:
случайное значение в [0, 1[ (включая 0, исключая 1):
#define ARC4RANDOM_MAX 0x100000000 ... double val = ((double)arc4random() / ARC4RANDOM_MAX);
немного подробнее здесь.
фактический диапазон составляет [0, 0.999999999767169356], так как верхняя граница (двойная) 0xFFFFFFFF / 0x100000000.
// 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].
для 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 бит точность (не рекомендуется)
легко достигнуть точности 48 битов с
drand48
(используетarc4random_buf
под капотом). Но обратите внимание, что 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 val = Float80(UInt64(arc4random()) << 32 &+ UInt64(arc4random())) / 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
который имеет точность significand 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-битные решения должны быть лучшими, которых мы можем достичь.
эта функция работает и для отрицательных диапазонов float:
float randomFloat(float Min, float Max){ return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min; }
(float)rand() / RAND_MAX
Предыдущее сообщение, в котором говорилось "rand ()", было неверным. Это правильный способ использования rand ().
это создаст число между 0 - > 1
BSD docs:
функция RAND() вычисляет последовательность псевдослучайных целых в
диапазоне от 0 до RAND_MAX (как определено в заголовочном файле "stdlib.ч.)"
Это расширение для 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 } }
Swift 4.2
Swift 4.2 включил собственный и довольно полнофункциональный API случайных чисел в стандартную библиотеку. (Swift Evolution proposal SE-0202)
let intBetween0to9 = Int.random(in: 0...9) let doubleBetween0to1 = Double.random(in: 0...1)
все типы чисел имеют статический random (in:) функция, которая принимает диапазон и возвращает случайное число в заданном диапазоне.
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)
Doc:
использовать это, чтобы избежать проблем с верхней границей arc4random()
u_int32_t upper_bound = 1000000; float r = arc4random_uniform(upper_bound)*1.0/upper_bound;
обратите внимание, что это применимо для MAC_10_7, IPHONE_4_3 и выше.
arc4random
имеет диапазон до 0x100000000 (4294967296)Это еще один хороший вариант для генерации случайных чисел от 0 до 1:
srand48(time(0)); // pseudo-random number initializer. double r = drand48();
float x = arc4random() % 11 * 0.1;
что производит случайный поплавок bewteen 0 и 1. подробнее здесь