Я пытаюсь сгенерировать случайное число от 0 до 1. Я продолжаю читать arc4random()
, но нет никакой информации о том, как получить от него float. Как мне это сделать?
ios
c
random
floating-point
arc4random
Джини
источник
источник
Ответы:
Случайное значение в [0, 1 [ (включая 0, исключая 1):
double val = ((double)arc4random() / UINT32_MAX);
Немного подробнее здесь .
Фактический диапазон составляет [0, 0,999999999767169356] , так как верхняя граница (двойная) 0xFFFFFFFF / 0x100000000.
источник
ARC4RANDOM_MAX
нужно определять вручную, но0x100000000
это 4294967296 , то естьULONG_MAX + 1
. Где это документально подтверждено , чтоarc4random()
Макс «s этоULONG_MAX
так или иначе?// Seed (only once) srand48(time(0)); double x = drand48(); // Swift version // Seed (only once) srand48(Int(Date().timeIntervalSince1970)) let x = drand48()
источник
drand48
необходимо инициализировать один раз с помощью семени. В документации Apple также предлагается инициализировать его.double
. См. Stackoverflow.com/a/34765674/1033581 о том, как добиться максимальной точности.Для 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 :
Оптимально для:
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 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)
Оптимально для:
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+
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)
Док:
random(in range: ClosedRange<Float>)
random(in range: Range<Float>)
random(in range: ClosedRange<Double>)
random(in range: Range<Double>)
random(in range: ClosedRange<Float80>)
random(in range: Range<Float80>)
источник
(float)rand() / RAND_MAX
Предыдущий пост, в котором говорилось только о "rand ()", был неверным. Это правильный способ использования rand ().
Это создаст число от 0 до 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 } }
источник
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 :), которая принимает диапазон и возвращает случайное число в данном диапазоне.
источник
Используйте это, чтобы избежать проблем с верхней границей 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
. Тем не менее, вы все равно будете иметь произвольно низкую точность, вызванную upper_bound, поэтому вам следует увеличить upper_bound до 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. Подробнее здесь
источник
по умолчанию производит случайное число (с плавающей запятой) от 0 до 1.
источник
rand()
похоже, не существует на iOS , и если бы он был, он бы выдал целое число, как и на всех других * NIX.rand()
является частью C, который, в свою очередь, является частью Objective-C (который используется в программировании iOS). Функции C вроде быrand()
абсолютно существуют в iOS, ноarc4random()
предпочтительнее.