Для 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-битные решения должны быть лучшими, которые мы можем достичь.