Я намагаюся згенерувати випадкове число від 0 до 1. Я продовжую читати arc4random()
, але інформації про отримання плаваючого з нього немає. Як це зробити?
Відповіді:
Випадкове значення в [0, 1 [ (включаючи 0, крім 1):
double val = ((double)arc4random() / UINT32_MAX);
Детальніше тут .
Фактичний діапазон - [0, 0,999999999767169356] , оскільки верхня межа (подвійна) 0xFFFFFFFF / 0x100000000.
ARC4RANDOM_MAX
це потрібно визначати вручну, але 0x100000000
це 4294967296 , що є ULONG_MAX + 1
. Де це задокументовано, що arc4random()
макс у ULONG_MAX
будь-якому випадку?
// 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].
drand48
потрібно ініціалізувати один раз за допомогою насіння. У документації Apple також пропонується ініціалізувати її.
double
. Див stackoverflow.com/a/34765674/1033581 про те , як досягти найкращої точності.
Про Swift 4.2+ див .: https://stackoverflow.com/a/50733095/1033581
Нижче наведено рекомендації щодо правильної однорідності та оптимальної точності для ObjC та Swift 4.1.
Float
)Рівномірне випадкове значення в [0, 1] (включаючи 0.0 та 1.0), точність до 32 біт:
Obj-C :
float val = (float)arc4random() / UINT32_MAX;
Стрімкий :
let val = Float(arc4random()) / Float(UInt32.max)
Це оптимально для:
Float
(або Float32
) який має значущу і точність 24 біти для своєї мантисиЛегко досягти точності 48 біт за допомогою drand48
( що використовується arc4random_buf
під капотом ). Але зауважте, що drand48 має недоліки через потребу в насінні, а також через те, що він неоптимальний для рандомізації всіх 52 бітів Double mantissa.
Рівномірне випадкове значення в [0, 1] , точність 48 біт:
Стрімкий :
// seed (only needed once)
srand48(Int(Date.timeIntervalSinceReferenceDate))
// random Double value
let val = drand48()
Double
та Float80
)Рівномірне випадкове значення в [0, 1] (включаючи 0.0 та 1.0), точність до 64 біт:
Свіфт , використовуючи два виклики arc4random:
let arc4random64 = UInt64(arc4random()) << 32 &+ UInt64(arc4random())
let val = Float80(arc4random64) / Float80(UInt64.max)
Свіфт , використовуючи один виклик до arc4random_buf:
var arc4random64: UInt64 = 0
arc4random_buf(&arc4random64, MemoryLayout.size(ofValue: arc4random64))
let val = Float80(arc4random64) / Float80(UInt64.max)
Це оптимально для:
Double
(або Float64
) який має значущу точність 52 біти для своєї мантиси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-бітні рішення повинні бути найкращими, яких ми можемо досягти.
Ця функція працює і для від'ємних плаваючих діапазонів:
float randomFloat(float Min, float Max){
return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}
Min+(Max-Min)*((float)arc4random())/ULONG_MAX
замість цього. Акторський (float)
склад - просто параноїя.
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)
Док:
(float)rand() / RAND_MAX
Попередній допис із зазначенням "rand ()" був неправильним. Це правильний спосіб використання rand ().
Це створить число від 0 -> 1
Документи BSD:
Функція rand () обчислює послідовність псевдовипадкових цілих чисел у
діапазоні від 0 до RAND_MAX (як визначено в заголовковому файлі "stdlib.h").
Це розширення для випадкового числа Float 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
}
}
Свіфт 4.2
Swift 4.2 включив у стандартну бібліотеку власний і досить повнофункціональний API випадкових чисел. (Програма Swift Evolution SE-0202 )
let intBetween0to9 = Int.random(in: 0...9)
let doubleBetween0to1 = Double.random(in: 0...1)
Усі типи чисел мають статичну випадкову функцію (in :), яка приймає діапазон і повертає випадкове число в заданому діапазоні.
Використовуйте це, щоб уникнути проблем з верхньою межею arc4random ()
u_int32_t upper_bound = 1000000;
float r = arc4random_uniform(upper_bound)*1.0/upper_bound;
Зверніть увагу, що він застосовується для MAC_10_7, IPHONE_4_3 і вище.
upper_bound-1
. Тим не менш, у вас все одно буде довільно низька точність, спричинена верхньою межею, тому вам слід збільшити верхню межу до UINT32_MAX. І ви можете отримати ще кращу точність від використання arc4random()*1.0 / UINT32_MAX
замість arc4random_uniform(UINT32_MAX)*1.0 / (UINT32_MAX-1)
.
arc4random
має діапазон до 0x100000000 (4294967296)
Це ще один хороший варіант для створення випадкових чисел від 0 до 1:
srand48(time(0)); // pseudo-random number initializer.
double r = drand48();
float x = arc4random() % 11 * 0.1;
Це дає випадковий плаваючий інтервал між 0 і 1. Більше інформації тут
rand()
за замовчуванням створює випадкове число (плаваюче) від 0 до 1.
rand()
здається, не існує на iOS , і якби він існував, він би видав ціле число, як на кожному іншому * NIX.
rand()
є частиною C, яка в свою чергу є частиною Objective-C (яка використовується в програмуванні iOS). Функції C, як rand()
абсолютно існують на iOS, але arc4random()
є кращими.