rand 函数是不是在 MATLAB/Octave 中产生 0 或 1 的值?
Posted
技术标签:
【中文标题】rand 函数是不是在 MATLAB/Octave 中产生 0 或 1 的值?【英文标题】:Does the rand function ever produce values of 0 or 1 in MATLAB/Octave?rand 函数是否在 MATLAB/Octave 中产生 0 或 1 的值? 【发布时间】:2015-07-01 01:22:07 【问题描述】:我正在寻找一个能够在0
和1
之间生成随机值的函数,包括两者。我通过在八度音程中使用 rand()
函数生成了 120,000 个随机值,但没有一次将值 0
或 1
作为输出。 rand()
会产生这样的值吗?如果没有,我可以使用其他任何功能来达到预期的效果吗?
【问题讨论】:
【参考方案1】:如果你在Octave 和MATLAB 中阅读了rand
的文档,它是(0,1)
之间的open 间隔,所以不,它不应该生成数字 0或 1。
不过,您或许可以生成一组随机整数,然后将这些值标准化,使它们位于[0,1]
之间。所以也许使用类似randi
(MATLAB docs,Octave docs)的东西,它生成从1到给定最大值的整数值。有了这个,定义这个最大数,然后减 1 并除以这个偏移最大值,得到 [0,1]
之间的值:
max_num = 10000; %// Define maximum number
N = 1000; %// Define size of vector
out = (randi(max_num, N, 1) - 1) / (max_num - 1); %// Output
如果您希望它更像rand
但包括 0 和 1,请将 max_num
变量设置得非常大。
【讨论】:
不错的技巧 +1 :) 顺便说一句,我没有在文档中看到 open interval 部分。我错过了什么吗? @SanthanSalai - 在我的 MATLAB R2013a 文档中。我刚刚在 MathWorks 上查看了 MATLAB 文档,您确实是对的。 @SanthanSalai - 哦。感谢您的 +1 :) @rayryeng 尽管文档页面似乎出于某种原因删除了有关开放区间的详细信息,但它仍保留在帮助中(R2015a 中的help rand
)。
@Rayryeng:非常感谢。这真的很有帮助:)【参考方案2】:
在数学上,如果您从闭区间 [0 1] 上的(连续)均匀分布中采样,则值为 0 和 1(实际上是任何值)概率严格为零。
以编程方式,
如果您有一个随机生成器在 闭合 区间 [0 1] 上生成 double
类型的值,则获得值 0 或 1 的概率不为零,但它太小了,可以忽略。
如果随机生成器从 开 区间 (0, 1) 生成值,则获得值 0 或 1 的概率严格为零 .
所以概率要么严格为零,要么很小,可以忽略不计。因此,您不必担心:在任何一种情况下,出于实际目的,概率都为零。即使rand
属于上述类型 (1),因此 可以 产生 0
和 1
,它产生它们的概率也会很小,以至于您“永远不会”看到这些值。
这听起来很奇怪吗?好吧,任何数字都会发生这种情况。你“永远不会”看到rand
输出正好是 1/4。有很多可能的输出,所有这些输出的可能性都相同,任何给定输出的概率几乎为零。
【讨论】:
rand
不是从闭区间 [0,1]
中采样,而是从开区间 (0,1)
中采样。它永远不应该(不仅仅是非常罕见地)产生 1。
最好明确给出命中给定双值 (~1e-16) 的概率,而不是小到可以忽略。
@mbschenkel 如果rand
输出all 现有double
值介于0
和@ 之间,概率将为~1e-16(由eps
给出) 987654333@ 概率相同。尽管这对于rand
来说是最理想的行为,但我们不能确定情况是否真的如此,除非它被记录在案
@LuisMendo 质疑rand
是否以相同的概率给出所有输出并没有真正意义,因为它是一个伪 RNG。 Mersenne Twister 通过了严格的随机性测试(例如 Diehard),并且对于所有 k
@TasosPapastylianou 不知道 :-) 在我的情况下发生的事情是:我对这个答案表示赞成,这促使我重新阅读它,我不可避免地发现了一些可以改进的部分
【参考方案3】:
rand
从 open 区间 (0,1)
生成数字,其中不包括 0 或 1,因此您永远不应该获得这些值。这在以前的版本中有更清楚的记录,但是它仍然在rand
的帮助文本中说明(输入help rand
而不是doc rand
)。
但是,由于它产生双精度值,因此它实际产生的值的数量是有限的。精确的集合因使用的 RNG 算法而异。对于默认算法 Mersenne twister,可能的值都是 2^(-53) 的倍数,在开区间 (0,1)
内。 (有关其他生成器的信息,请参阅 doc RandStream.list
,然后是“选择随机数生成器”)。
请注意,2^(-53) 是 eps/2。因此,相当于从闭区间[2^(-53), 1-2^(-53)]
,或者[eps/2, 1-eps/2]
绘制。
您可以通过减去 eps/2 并除以 1-eps 来将此间隔缩放到 [0,1]
。 (使用format hex
显示足够的精度以在位级别进行检查)。
所以x = (rand-eps/2)/(1-eps)
应该给你闭区间[0,1]
的值。
但我应该提醒一句:他们已经付出了很多努力来确保rand
的输出在(0,1)
内给出任何给定双精度的适当分布,我不认为你'如果您应用我建议的缩放比例,将在 [0,1]
上获得相同的好属性。我对浮点数学和 RNG 的了解不足以解释为什么,或者你可能会怎么做。
【讨论】:
是否记录了最小值是eps(1)
而不是eps(0)
?对于eps(0)
,您的代码会生成负值。
@Daniel 我不确定您所说的“最低限度”是什么意思——最低限度是什么?我的回答是eps
,根据定义是eps(1)
,而不是eps(0)
——我没有建议在任何地方使用eps(0)
。
当rand
输出的最小值为eps(0)
时,您的代码将生成负值。 eps(0)
是最小的正双精度数,因此它可能由 rand
返回。不知道。
@Daniel 不,rand
(使用 Mersenne Twister 算法时)返回的最小值是 2^(-53) 或 eps/2,正如我在回答中提到的那样。我在回答中提到的文档页面中记录了这一点。
"rand 的帮助文本中还是有说明的(type help rand)": 帮助中没有了(4.2.2),所以谜团依然存在,除非文档中提到的(0,1)
可以理解为 0 和 1 的 exclusive,这似乎很可能。【参考方案4】:
我刚试过这个:
octave:1> max(rand(10000000,1))
ans = 1.00000
octave:2> min(rand(10000000,1))
ans = 3.3788e-08
没有严格地给我0,所以要注意浮点运算。
编辑
尽管我说过,注意浮点运算我确实上当了。正如@eigenchris 指出的那样:
format long g
octave:1> a=max(rand(1000000,1))
a = 0.999999711020176
它产生一个接近的浮点数,不等于,正如@rayryeng 建议的那样,在更改精度后您现在可以看到。
【讨论】:
您可能想检查这是否真的是1.0
,或者只是浮点数的四舍五入版本。
很好,不是 1 只是 Octave 的显示,我会修复答案
@brodroll - 尝试更改显示格式。执行format long g;
然后再次尝试运行代码。我已经运行了好几次,但我从来没有得到确切的1.0
。这是我的 Octave 实例上的一次运行。顺便说一句 +1 为您的答案。 octave:1> format long g; octave:2> max(rand(100000000,1)) ans = 0.999999988570948 octave:3> format octave:4> ans ans = 1.00000
是的,做出了更改以供进一步参考和完成。感谢您的提醒!【参考方案5】:
虽然不是直接针对此处的问题,但我发现链接到此 SO 帖子 Octave - random generate number 很有帮助,该帖子有一个使用 r = rand > 0.5
生成 1 和 0 的衬线。
【讨论】:
以上是关于rand 函数是不是在 MATLAB/Octave 中产生 0 或 1 的值?的主要内容,如果未能解决你的问题,请参考以下文章
Octave / MATLAB 中的 deal() 函数有啥意义?
如何在 Matlab/Octave `mexFunction`(不是 nrhs)中确定数组的大小
MATLAB 或 Octave 的自动缩进清理器? [关闭]