产生介于0和1之间的随机浮点数


84

我试图生成一个介于0和1之间的随机数arc4random()。我该怎么做呢?


1
不是重复项,这似乎是与浮点数明确相关的唯一问题。
P I

Answers:


139

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

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

这里有更多细节。

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


谢谢。我见过的最直接的答案。我将阅读您的链接,并获取更多详细信息。再次感谢。
jini 2011年

3
ARC4RANDOM_MAX必须手动定义它很奇怪,但是它0x100000000是4294967296,即ULONG_MAX + 1。无论如何,哪里记录了arc4random()max ULONG_MAX
bobobobo 2012年

@bobobobo,来自此处:developer.apple.com/library/mac/#documentation/Darwin/Reference/…arc4random()函数返回伪随机数,范围为0到(2 ** 32)-1
弗拉基米尔

8
实际上,该值应为0xFFFFFFFF,(2 ** 32)-1 == 0x100000000-0x1 == 0xFFFFFFFF == UINT32_MAX,如JörgBühmann当前在链接上所述。
Josejulio 2014年

1
不能保证以这种方式生成的值是均匀分布的!
凯林2015年

107
// 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]上。


19
这应该是最好的答案。
John Riselvato

您可能只需要更新一点答案,我在NSHipster阅读过drand48需要使用种子将其初始化一次。在苹果的文件还表明,它应该被初始化。
dulaccc 2014年

1
需要种子是因为它为该随机生成器提供了计算的起点。如果没有它,则随机序列在应用程序启动时始终是相同的。
Jovan Stankovic

这是最好的答案。
萨比兰郡'17

此答案不是的最佳精度答案double。有关如何获得最佳精度的信息,请参见stackoverflow.com/a/34765674/1033581
心教堂

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;

斯威夫特

let val = Float(arc4random()) / Float(UInt32.max)

最适合:

  • 一个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()

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位精度arc4randomarc4random_uniformrandrandom。因此,我们上面的32位和64位解决方案应该是我们可以达到的最佳解决方案。


“ Float80”在实际的iOS设备上不可用(仅在模拟器上有效)。
心教堂

10

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

float randomFloat(float Min, float Max){
    return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}

4
无关的模数运算。使用Min+(Max-Min)*((float)arc4random())/ULONG_MAX代替。该(float)投只是妄想。
bobobobo 2012年

@bobobobo虽然我同意无关紧要的模数,但我建议用UINT32_MAX(始终为4294967295)除以ULONG_MAX(64位为18446744073709551615)。
心教堂


1
(float)rand() / RAND_MAX

以前仅指出“ rand()”的帖子是不正确的。这是使用rand()的正确方法。

这将在0-> 1之间创建一个数字

BSD文档:

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


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
    }
}

@Cœur谢谢您我更改了
YannSteph


0

使用它来避免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。但是,由于upper_bound造成的精度仍然会任意降低,因此应将upper_bound增大为UINT32_MAX。使用arc4random()*1.0 / UINT32_MAX而不是可以获得更高的精度arc4random_uniform(UINT32_MAX)*1.0 / (UINT32_MAX-1)
心教堂


-4
float x = arc4random() % 11 * 0.1;

产生一个随机浮点bewteen 0和1。 更多资讯


3
注意:仅提供11个离散值:
0.0、0.1、0.2

8
是的,模运算将arc4random()的结果切为0到10之间,然后将其除以10。这个答案对于一般用途来说确实是不好的。
bobobobo 2012年

-4
rand() 

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


4
这为我产生了一个随机整数。
AlexQueue

rand()似乎在iOS上存在,如果它没有,它会像它的所有其他* NIX产生一个整数。
jscs

2
@JoshCaswellrand()是C的一部分,而C又是Objective-C(在iOS编程中使用)的一部分。C函数rand()绝对存在于iOS上,但是arc4random()首选。
弗鲁吉(Frungi)2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.