Згенеруйте випадковий плаваючий інтервал від 0 до 1


84

Я намагаюся згенерувати випадкове число від 0 до 1. Я продовжую читати arc4random(), але інформації про отримання плаваючого з нього немає. Як це зробити?


1
Не повторюється, це, здається, єдине питання, яке явно стосується поплавців.
P i

Відповіді:


139

Випадкове значення в [0, 1 [ (включаючи 0, крім 1):

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

Детальніше тут .

Фактичний діапазон - [0, 0,999999999767169356] , оскільки верхня межа (подвійна) 0xFFFFFFFF / 0x100000000.


Дякую. Я бачив найбільш пряму відповідь. Я прочитаю ваше посилання та отримаю додаткову інформацію про це. Знову дякую.
джині 02.03.11

3
Дивно, що ARC4RANDOM_MAXце потрібно визначати вручну, але 0x100000000це 4294967296 , що є ULONG_MAX + 1. Де це задокументовано, що arc4random()макс у ULONG_MAXбудь-якому випадку?
bobobobo

@bobobobo, звідси: developer.apple.com/library/mac/#documentation/Darwin/Reference/… Функція arc4random () повертає псевдовипадкові числа в діапазоні від 0 до (2 ** 32) -1
Володимир

8
Насправді значення має бути 0xFFFFFFFF, (2 ** 32) -1 == 0x100000000 - 0x1 == 0xFFFFFFFF == UINT32_MAX, як зазначено в даний момент Йоргом Бюхманом за посиланням.
Хосехуліо

1
Створені таким чином значення не гарантуються рівномірним розподілом!
kelin

107
// 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].


19
Це повинна бути найкраща відповідь.
Джон Рісельвато,

Можливо, вам потрібно лише трохи оновити відповідь, я читав на NSHipster, яку drand48потрібно ініціалізувати один раз за допомогою насіння. У документації Apple також пропонується ініціалізувати її.
dulaccc 02

1
Насіння потрібно, оскільки воно дає цьому випадковому генератору вихідну точку для розрахунків. Без цього випадкова послідовність завжди була б однаковою при запуску додатків.
Йован Станкович

Це найкраща відповідь.
sabiland

Ця відповідь не є оптимальною точністю відповіді для double. Див stackoverflow.com/a/34765674/1033581 про те , як досягти найкращої точності.
Cœur

16

Про 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;

Стрімкий :

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

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

  • a Float(або Float32) який має значущу і точність 24 біти для своєї мантиси

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

Легко досягти точності 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()

Точність 64 біт (оптимальна для 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)

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

  • 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-бітні рішення повинні бути найкращими, яких ми можемо досягти.


'Float80' недоступний на реальних пристроях iOS (він працює лише на симуляторі).
Кер

10

Ця функція працює і для від'ємних плаваючих діапазонів:

float randomFloat(float Min, float Max){
    return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}

4
Робота стороннього модуля. використовувати Min+(Max-Min)*((float)arc4random())/ULONG_MAXзамість цього. Акторський (float)склад - просто параноїя.
bobobobo

@bobobobo, хоча я погоджуюсь на сторонній модуль, я раджу розділити на UINT32_MAX (4294967295 завжди) замість ULONG_MAX (18446744073709551615 на 64 біти).
Cœur,


1
(float)rand() / RAND_MAX

Попередній допис із зазначенням "rand ()" був неправильним. Це правильний спосіб використання rand ().

Це створить число від 0 -> 1

Документи BSD:

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


1

Це розширення для випадкового числа 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
    }
}

@ Cœur Дякую, я змінив це
YannSteph

1

Свіфт 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 :), яка приймає діапазон і повертає випадкове число в заданому діапазоні.


0

Використовуйте це, щоб уникнути проблем з верхньою межею arc4random ()

u_int32_t upper_bound = 1000000;

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

Зверніть увагу, що він застосовується для MAC_10_7, IPHONE_4_3 і вище.


З цим існує фундаментальна проблема асортименту. Це легко помітно, коли ви встановлюєте для верхньої межі значення 10, arc4random_uniform поверне значення від 0 до 9, а кінцевий результат буде від 0,0000 до 0,9000. Натомість слід поділити на upper_bound-1. Тим не менш, у вас все одно буде довільно низька точність, спричинена верхньою межею, тому вам слід збільшити верхню межу до UINT32_MAX. І ви можете отримати ще кращу точність від використання arc4random()*1.0 / UINT32_MAXзамість arc4random_uniform(UINT32_MAX)*1.0 / (UINT32_MAX-1).
Cœur

-1

arc4random має діапазон до 0x100000000 (4294967296)

Це ще один хороший варіант для створення випадкових чисел від 0 до 1:

srand48(time(0));      // pseudo-random number initializer.
double r = drand48();

arc4random максимальне значення 0xFFFFFFFF
Cœur

Дякую @ Cœur ..max val 0xFFFFFFFF я не знав
Gurunatha Dogi

ваше рішення також ідентично відповіді Йована Станковича.
Cœur,

Ох, я цього не бачив @ Cœur
Gurunatha Dogi

-4
float x = arc4random() % 11 * 0.1;

Це дає випадковий плаваючий інтервал між 0 і 1. Більше інформації тут


3
Примітка: дається лише 11 дискретних значень: 0,0, 0,1, 0,2, ..., 1,0
TalkLittle

8
Так, операція модуля скорочує результат arc4random () до 0 і 10, тоді він ділить його на 10. Ця відповідь насправді погана для загального користування.
bobobobo

-4
rand() 

за замовчуванням створює випадкове число (плаваюче) від 0 до 1.


4
Це створює випадковий int для мене.
AlexQueue

rand()здається, не існує на iOS , і якби він існував, він би видав ціле число, як на кожному іншому * NIX.
jscs

2
@JoshCaswell rand()є частиною C, яка в свою чергу є частиною Objective-C (яка використовується в програмуванні iOS). Функції C, як rand()абсолютно існують на iOS, але arc4random()є кращими.
Frungi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.