【问题标题】:Is there an IDIOMATIC way to get a random Fixnum in Ruby?是否有一种 IDIOMATIC 方法可以在 Ruby 中获取随机的 Fixnum?
【发布时间】:2014-09-22 18:57:10
【问题描述】:

我正在使用一种使用随机数的算法。如果能够最大化我可以获得的随机性,同时保持数字是一个性能合理的整数,那就太好了,所以理想情况下它们应该在Fixnum::MIN .. Fixnum::MAX 的范围内,但0..Fixnum::MAX 也应该没问题。

哦,等等。这些常量实际上并不存在。所以当你读到Random.rand returns a float unless you pass it an integer argument 时,唯一明显的做法就是resort to terrible hacks like these

在 Ruby 中是否有更惯用的方法来获取随机整数,或者如果我想要这种能力,Yukihiro 是否只是希望我的代码变得丑陋并重复可疑的整数大小幂运算?

【问题讨论】:

  • 你的意思是一个无限大小的随机整数?这几乎从来都不是你真正需要的。你的实际上限是多少?
  • @RobertHarvey - 这正是教科书实现在该算法中所要求的:一堆元素获得随机权重,它们相互比较的原因(没有其他数学是在这些对象上执行)。它们可能是我关心的所有字符串,但如果它们很快就会很好。碰撞不会影响算法的正确性,偶尔的碰撞只会对性能产生微不足道的影响,但同时实际上没有必要使随机可比较池比必要的小,并且可能涉及 ALL_YOUR_RAM 数量的元素。跨度>
  • 那么你的实际上限是多少?它不可能是无限的。
  • 我怀疑这里的实际答案是“使用可怕的黑客,继续生活。”
  • @daremkd AFAIK,Kernel#rand 并不总是将 Range 对象作为参数,但它现在似乎可以在 Ruby 2.1.2 上使用。我的回答略有不同,但您的范围似乎在数百万次试验中运行良好。测试代码见this gist

标签: ruby random idioms


【解决方案1】:

0..FIXNUM_MAX 的随机值

当 Fixnum 溢出时,Ruby 只会转换为 Bignum。但是,this related answer 显示了如何为您的平台计算 Fixnum 的最小值和最大值。以此为起点,您可以获得所需范围内的正整数:

FIXNUM_MAX = (2**(0.size * 8 -2) -1)
Random.rand FIXNUM_MAX

负整数

如果您也坚持使用负数,那么对于您的目的而言,以下内容可能“足够接近”,即使 FIXNUM_MIN.abs == FIXNUM_MAX 在您的平台上可能是错误的:

FIXNUM_MAX = (2**(0.size * 8 -2) -1)
random_num = Random.rand FIXNUM_MAX
random_num.even? ? random_num : random_num * -1

另见

【讨论】:

    【解决方案2】:

    这应该会为您提供相当多的样本整数:

    require "securerandom"
    exponent = rand(1..15)
    puts (SecureRandom.random_number * 10**exponent).to_i
    

    一种更快的工作算法,产生相同或可能更好的随机性:

    r = Random.new
    exponent = rand(1..15)
    puts (r.rand * 10**exponent).to_i
    

    甚至更简单的方法:

    FIXNUM_MAX = (2**(0.size * 8 -2) -1)
    FIXNUM_MIN = -(2**(0.size * 8 -2))
    p rand(FIXNUM_MIN..FIXNUM_MAX)
    

    【讨论】:

    • 所以你的最后一个例子是错误的并且经常返回Bignum对象。 p (1..5).map { rand(0..2**64-1).class } => [Fixnum, Bignum, Bignum, Bignum, Bignum]
    • 抱歉,没有读到您只是在寻找 fixnums,编辑了这个问题,所以现在最后一个示例将为您提供从最小到最大 fixnum 的所有数字。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 2011-01-27
    • 2010-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多