生成0到1之间的随机浮点数

jin*_*ini 82 c random floating-point arc4random ios

我正在尝试生成一个介于0和1之间的随机数.我一直在阅读arc4random(),但是没有关于从中获取浮点数的任何信息.我该怎么做呢?

Vla*_*mir 136

[0,1 [(包括0,不包括1)中的随机值:

double val = ((double)arc4random() / UINT32_MAX);
Run Code Online (Sandbox Code Playgroud)

这里有更多细节.

实际范围是[0,0.999999999767169356],因为上限是(double)0xFFFFFFFF/0x100000000.

  • 实际上,该值应为0xFFFFFFFF,(2**32)-1 == 0x100000000 - 0x1 == 0xFFFFFFFF == UINT32_MAX,如JörgBühmann目前在链接中所述. (8认同)
  • 奇怪的是,"ARC4RANDOM_MAX"必须手动定义,但是[`0x100000000`是4294967296](http://www.google.com/#hl=en&q=0x100000000+in+decimal),这是[`ULONG_MAX + 1 `](http://www.cplusplus.com/reference/clibrary/climits/).哪里记载`arc4random()`的最大值无论如何都是`ULONG_MAX`? (3认同)

Jov*_*vic 106

// Seed (only once)
srand48(time(0));

double x = drand48();

// Swift version
// Seed (only once)
srand48(Int(Date().timeIntervalSince1970))

let x = drand48()
Run Code Online (Sandbox Code Playgroud)

drand48()和erand48()函数返回非负的,双精度的浮点值,均匀分布在区间[0.0,1.0]上.

  • 这应该是最好的答案. (19认同)

Cœu*_*œ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;
Run Code Online (Sandbox Code Playgroud)

斯威夫特:

let val = Float(arc4random()) / Float(UInt32.max)
Run Code Online (Sandbox Code Playgroud)

它最适合:

  • a Float(或Float32)其尾数的有效位精度为24位

48位精度(不鼓励)

它很容易达到48位精度drand48(在引擎盖下使用arc4random_buf).但请注意,drand48由于种子需求而存在缺陷,并且对于将所有52位双尾数随机化而言也是次优的.

[0,1]中的均匀随机值,48位精度:

斯威夫特:

// seed (only needed once)
srand48(Int(Date.timeIntervalSinceReferenceDate))
// random Double value
let val = drand48()
Run Code Online (Sandbox Code Playgroud)

64位精度(最适合DoubleFloat80)

[0,1]中的均匀随机值(包括0.0和1.0),最高64位精度:

Swift,使用两次对arc4random的调用:

let arc4random64 = UInt64(arc4random()) << 32 &+ UInt64(arc4random())
let val = Float80(arc4random64) / Float80(UInt64.max)
Run Code Online (Sandbox Code Playgroud)

Swift,使用一次对arc4random_buf的调用:

var arc4random64: UInt64 = 0
arc4random_buf(&arc4random64, MemoryLayout.size(ofValue: arc4random64))
let val = Float80(arc4random64) / Float80(UInt64.max)
Run Code Online (Sandbox Code Playgroud)

它最适合:

  • 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,randrandom.因此,我们的32位和64位解决方案应该是我们能够实现的最佳解决方案.


小智 10

此函数也适用于负浮点范围:

float randomFloat(float Min, float Max){
    return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}
Run Code Online (Sandbox Code Playgroud)

  • 外来模数操作.使用`Min +(Max-Min)*((float)arc4random())/ ULONG_MAX`代替.`(浮动)`演员只是偏执狂. (4认同)

Cœu*_*œur 5

迅捷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)
Run Code Online (Sandbox Code Playgroud)

文件: