我试图调试Sonic Pi 2.0中的一个样本(Raspberry Pi上的SuperCollider的Ruby包装器)。我已经将问题代码缩小到这几行简单的Ruby:
loop do
s = 0.2 + rand(0.3)
e = s + 0.0625
puts 's = ' + s.to_s + ', e = ' + e.to_s
sleep 1
end
看the documenation我希望每次循环都会被设置为0.2到0.5之间的值。但不,这是一个典型的结果:
==> Starting run 143 [Run 143, Time 0.0] +- s = 0.6204361822133666, e = 0.6829361822133666 [Run 143, Time 1.0] +- s = 0.2832891087607155, e = 0.3457891087607155 [Run 143, Time 2.0] +- s = 0.4914545052249532, e = 0.5539545052249533 [Run 143, Time 3.0] +- s = 0.8560154313773802, e = 0.9185154313773802 [Run 143, Time 4.0] +- s = 1.1902533463314418, e = 1.2527533463314418
s
的高值来自哪些想法?
答案 0 :(得分:7)
这是因为您传递的值小于1 max
。 Ruby实际上对参数执行了abs.to_i
,如果它的计算结果为零,rand
将返回0到1之间的数字。
示例:
> rand(0.3) # 0.3.abs.to_i evaluates to 0
=> 0.5406754757491508
有关详细信息,请参阅the docs。他们甚至对这个特定问题发表评论:
允许使用最大值的负值或浮点值,但可能会产生令人惊讶的结果。
如果您想获得0到0.3之间的数字,请执行以下操作:
rand * 0.3
或者正如维克多指出的那样,你可以使用Random.rand按预期工作:
Random.rand(0.3) # this will always be >= 0 and < 0.3
答案 1 :(得分:1)
您在rand上使用的最大参数的行为与预期的不同:
它在文档中说:
当max.abs大于或等于1时,rand返回a 伪随机整数大于或等于0且小于 max.to_i.abs。
所以rand(0.3)可以得到0.9这样的值,因此
答案 2 :(得分:1)
rand
(内核#rand,你正在使用的那个)和Random#rand
(你链接的文档中的那个)之间存在差异。
您应该在代码中使用Random#rand。