我试图生成一个介于0和1之间的随机数arc4random()
。我该怎么做呢?
Answers:
[0,1 [(包括0,不包括1)中的随机值:
double val = ((double)arc4random() / UINT32_MAX);
这里有更多细节。
实际范围是[0,0.999999999767169356],因为上限是(double)0xFFFFFFFF / 0x100000000。
ARC4RANDOM_MAX
必须手动定义它很奇怪,但是它0x100000000
是4294967296,即ULONG_MAX + 1
。无论如何,哪里记录了arc4random()
max 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]上。
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位随机化都不理想。
[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位精度:
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为范围内的随机值添加了本机支持:
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随机数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)
所有数字类型都具有静态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;
产生一个随机浮点bewteen 0和1。 更多资讯
rand()
默认情况下会产生一个介于0和1之间的随机数(浮点数)。
rand()
是C的一部分,而C又是Objective-C(在iOS编程中使用)的一部分。C函数rand()
绝对存在于iOS上,但是arc4random()
首选。