我想生成一个在0到1之间的随机数。我一直在阅读关于arc4random()
的内容,但没有关于如何从中获取浮点数的信息。我该怎么办?
我正在尝试生成介于0到1之间的随机数字。我一直读到了有关arc4random()
的文章,但是没有任何关于如何从中获取浮点数的信息。请问应该如何操作?
我想生成一个在0到1之间的随机数。我一直在阅读关于arc4random()
的内容,但没有关于如何从中获取浮点数的信息。我该怎么办?
我正在尝试生成介于0到1之间的随机数字。我一直读到了有关arc4random()
的文章,但是没有任何关于如何从中获取浮点数的信息。请问应该如何操作?
生成 [0, 1) 区间内(包括0但不包括1)的随机值:
double val = ((double)arc4random() / UINT32_MAX);
更多细节在这里。
实际范围为[0,0.999999999767169356],因为上限是(double)0xFFFFFFFF / 0x100000000。
ARC4RANDOM_MAX
是什么类型?我想将其定义为一个变量。 - Iulian Onofrei// 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]。
double
数据类型并不具有最优精度。请查看https://dev59.com/oW435IYBdhLWcg3w20B8#34765674,了解如何实现最佳精度。 - Cœur查看Swift 4.2以上版本的内容,请参见:https://dev59.com/oW435IYBdhLWcg3w20B8#50733095
以下是ObjC和Swift 4.1的正确统一性和最佳精度建议。
在[0, 1]范围内产生具有32位精度(包括0.0和1.0)的均匀随机值:
Obj-C:
float val = (float)arc4random() / UINT32_MAX;
Swift:
let val = Float(arc4random()) / Float(UInt32.max)
最优选择是:
Float
(或 Float32
),它的尾数精度为 24 位使用 drand48
(在内部使用 arc4random_buf
)可以轻松实现 48 位精度。但请注意,由于种子需求以及随机化所有双精度尾数 52 位的不足之处,此方法存在缺陷。
[0, 1] 范围内的均匀随机值,精度为 48 位:
Swift:
// seed (only needed once)
srand48(Int(Date.timeIntervalSinceReferenceDate))
// random Double value
let val = drand48()
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)单次调用 arc4random
、arc4random_uniform
、rand
或 random
不可能获得超过 32 位的精度。因此,我们上述的 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)
转换只是谨慎起见。 - boboboboSwift 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>)
:生成在指定闭区间内的随机80位浮点数。random(in range: Range<Float80>)
:生成在指定半开区间内的随机80位浮点数。Swift 4.2
Swift 4.2在标准库中包含了一个本地且相当完整的随机数API。(Swift进化提案SE-0202)
let intBetween0to9 = Int.random(in: 0...9)
let doubleBetween0to1 = Double.random(in: 0...1)
这是针对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
}
}
(float)rand() / RAND_MAX
之前的帖子声称仅使用"rand()"是不正确的。 以下是正确使用rand()的方法。
这将创建一个介于0-1之间的数字
BSD文档:
rand()函数计算0到RAND_MAX(由头文件"stdlib.h"定义)范围内的伪随机整数序列。
使用此方法可避免与arc4random()的上限问题
u_int32_t upper_bound = 1000000;
float r = arc4random_uniform(upper_bound)*1.0/upper_bound;
upper_bound-1
。然而,由于upper_bound引起的任意低精度仍然存在,因此您应该将upper_bound增加到UINT32_MAX。使用arc4random()*1.0 / UINT32_MAX
而不是arc4random_uniform(UINT32_MAX)*1.0 / (UINT32_MAX-1)
可以获得更好的精度。 - Cœurarc4random
的范围高达0x100000000(4294967296)
这是另一个生成0到1之间随机数的好选择:
srand48(time(0)); // pseudo-random number initializer.
double r = drand48();