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

Posted

技术标签:

【中文标题】生成 0 到 1 之间的随机浮点数【英文标题】:Generate a random float between 0 and 1 【发布时间】:2011-07-07 13:02:35 【问题描述】:

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

【问题讨论】:

不重复,这似乎是唯一与浮动有关的问题。 【参考方案1】:

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

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

更多细节here。

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

【讨论】:

谢谢。我见过的最直接的答案。我将阅读您的链接并获得更多详细信息。再次感谢。 奇怪的是ARC4RANDOM_MAX必须手动定义,但是0x100000000 is 4294967296,即ULONG_MAX + 1。在哪里记录了arc4random() 的最大值是ULONG_MAX 无论如何? @bobobobo,来自这里:developer.apple.com/library/mac/#documentation/Darwin/Reference/… arc4random() 函数返回 0 到 (2**32)-1 范围内的伪随机数 实际上,该值应该是 0xFFFFFFFF,(2**32)-1 == 0x100000000 - 0x1 == 0xFFFFFFFF == UINT32_MAX,正如 Jörg Bühmann 目前在链接上所说的那样。 以这种方式生成的值不保证均匀分布!【参考方案2】:

对于 Swift 4.2+,请参阅:https://***.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)

最适合:

一个Float(或Float32),其尾数的有效位精度为24位

48 位精度(不鼓励)

使用drand48 (which uses arc4random_buf under the hood) 可以轻松实现 48 位精度。但请注意,drand48 has flaws 是因为需要种子,并且对于随机化所有 52 位双尾尾数不是最优的。

[0, 1]中的统一随机值,48位精度:

斯威夫特

// seed (only needed once)
srand48(Int(Date.timeIntervalSinceReferenceDate))
// random Double value
let val = drand48()

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)

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() (secretly using arc4random),最佳精度为 1 / 0x7FFFFFFF (RAND_MAX) 使用random() (secretly using arc4random),最佳精度为 1 / 0x7FFFFFFF (RAND_MAX)

单次调用arc4randomarc4random_uniformrandrandom 在数学上是不可能达到超过 32 位的精度的。所以我们上面32位和64位的方案应该是我们能做到的最好的了。

【讨论】:

'Float80' 在真实的 ios 设备上不可用(它只适用于模拟器)。【参考方案3】:

斯威夫特 4.2+

Swift 4.2 添加了对 Range 中随机值的原生支持:

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&lt;Float&gt;) random(in range: Range&lt;Float&gt;) random(in range: ClosedRange&lt;Double&gt;) random(in range: Range&lt;Double&gt;) random(in range: ClosedRange&lt;Float80&gt;) random(in range: Range&lt;Float80&gt;)

【讨论】:

【参考方案4】:

斯威夫特 4.2

Swift 4.2 在标准库中包含了一个原生且功能相当全面的随机数 API。 (Swift Evolution proposal SE-0202)

let intBetween0to9 = Int.random(in: 0...9) 
let doubleBetween0to1 = Double.random(in: 0...1)

所有数字类型都有静态 random(in:) 函数,该函数获取范围并返回给定范围内的随机数。

【讨论】:

【参考方案5】:

这是浮点随机数的扩展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 谢谢你我改变了【参考方案6】:

arc4random 的范围最大为 0x100000000 (4294967296)

这是生成 0 到 1 之间随机数的另一个不错的选择:

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

【讨论】:

arc4random 最大值为 0xFFFFFFFF 谢谢@Cœur ..max val 0xFFFFFFFF 我不知道 您的解决方案也与 Jovan Stankovic 的答案相同。 哦,我没看到@Cœur【参考方案7】:
// 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] 上。

【讨论】:

这应该是最好的答案了。 你可能只需要更新一点答案,我read on NSHipster drand48 需要用种子初始化一次。 Apple documentation 也建议初始化。 需要种子,因为它为这个随机生成器提供了计算的起点。如果没有它,随机顺序在应用启动时总是相同的。 这是最好的答案。 这个答案不是double 的最佳精确答案。请参阅***.com/a/34765674/1033581,了解如何获得最佳精度。【参考方案8】:

使用它来避免 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 设置为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),您可以获得更高的精度。【参考方案9】:
(float)rand() / RAND_MAX

上一篇单独声明“rand()”的帖子是不正确的。 这是使用 rand() 的正确方法。

这将创建一个介于 0 -> 1 之间的数字

BSD 文档:

rand() 函数计算 中的伪随机整数序列 范围为 0 到 RAND_MAX(由头文件“stdlib.h”定义)。

【讨论】:

【参考方案10】:
rand() 

默认产生一个介于 0 和 1 之间的随机数(浮点数)。

【讨论】:

这会为我生成一个随机整数。 rand() 没有 seem to exist on iOS,如果有,它会像在其他所有 *NIX 上一样产生一个整数。 @JoshCaswell rand() 是 C 的一部分,而 C 又是 Objective-C(用于 iOS 编程)的一部分。 rand() 之类的 C 函数绝对存在于 iOS 上,但首选 arc4random()【参考方案11】:

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

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) 演员只是偏执狂。 @bobobobo 虽然我同意无关模数,但我建议除以 UINT32_MAX(始终为 4294967295)而不是 ULONG_MAX(64 位上为 18446744073709551615)。【参考方案12】:
float x = arc4random() % 11 * 0.1;

这会产生一个介于 0 和 1 之间的随机浮点数。 More info here

【讨论】:

注:只给出11个离散值:0.0, 0.1, 0.2, ..., 1.0 是的,取模运算将 arc4random() 的结果减少到 0 到 10 之间,然后他将其除以 10。这个答案对于一般用途来说确实很糟糕。

以上是关于生成 0 到 1 之间的随机浮点数的主要内容,如果未能解决你的问题,请参考以下文章

php随机浮点数都有哪些?比如从0.1到3.0中随机一个浮点数出来?

0到1.0 php之间的随机浮点数[重复]

获取 0.0200 到 0.120 之间的随机数(浮点数)[重复]

JMeter 如何生成指定取值范围指定小数位数的随机浮点数

JMeter 如何生成指定取值范围指定小数位数的随机浮点数

Python玩转随机数,妈妈再也不会担心我不会随机数了