84

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

4

12 回答 12

140

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

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

这里有更多细节。

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

于 2011-03-02T19:35:42.270 回答
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] 上。

于 2013-06-05T10:37:04.923 回答
15

对于 Swift 4.2+,请参阅:https ://stackoverflow.com/a/50733095/1033581


以下是针对 ObjC 和 Swift 4.1 的正确一致性和最佳精度的建议。

32 位精度(最适合Float

[0, 1]中的统一随机值(包括 0.0 和 1.0),最高 32 位精度:

对象-C

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

斯威夫特

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

它最适合:

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

48 位精度(不鼓励)

drand48使用(在引擎盖下使用arc4random_buf)很容易实现 48 位精度。但请注意,drand48 存在缺陷,因为需要种子,并且对于随机化所有 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)

它最适合:

  • a Double(or Float64),其尾数的有效精度为 52 位
  • aFloat80其尾数的有效精度为 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或.在数学上不可能达到超过 32 位的rand精度random。所以我们上面的32位和64位解决方案应该是我们能做到的最好的了。

于 2016-01-13T11:36:21.203 回答
10

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

float randomFloat(float Min, float Max){
    return ((arc4random()%RAND_MAX)/(RAND_MAX*1.0))*(Max-Min)+Min;
}
于 2012-05-03T18:19:31.730 回答
7

斯威夫特 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)

文件:

于 2018-06-07T04:44:45.023 回答
1
(float)rand() / RAND_MAX

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

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

BSD 文档:


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

于 2013-01-31T07:33:40.517 回答
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
    }
}
于 2017-09-06T01:51:37.437 回答
1

斯威夫特 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:)函数,该函数获取范围并返回给定范围内的随机数。

于 2018-06-10T18:29:13.130 回答
0

使用它来避免arc4random()的上限问题

u_int32_t upper_bound = 1000000;

float r = arc4random_uniform(upper_bound)*1.0/upper_bound;

请注意,它适用于 MAC_10_7、IPHONE_4_3 及更高版本。

于 2014-02-28T17:51:35.543 回答
-1

arc4random范围最大为 0x100000000 (4294967296)

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

srand48(time(0));      // pseudo-random number initializer.
double r = drand48();
于 2017-09-27T05:31:07.230 回答
-4
float x = arc4random() % 11 * 0.1;

这会在 0 和 1 之间产生一个随机浮点数。 更多信息在这里

于 2012-01-26T17:18:37.250 回答
-4
rand() 

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

于 2012-10-31T18:35:04.803 回答