为什么Ruby的Array#count对于大型数组不可靠?

时间:2018-10-02 18:39:11

标签: arrays ruby

我正在迭代一个相当大的数组的2个元素的组合。当计算组合的元素时,我发现有些奇怪。以下示例显示了我的意思:

[1] pry(main)> 10000.times.to_a.combination(2).count
=> 49995000   # correct

[2] pry(main)> 100000.times.to_a.combination(2).count
=> 704982704  # wrong, should be 4999950000

[3] pry(main)> count = 0; 100000.times.to_a.combination(2).each { count+=1 }; count
=> 4999950000 # correct

我使用wolframalpha仔细检查了结果:

我的问题确实是,为什么Array#count在这种情况下不可靠?

另外,请参见https://ruby-doc.org/core-2.2.0/Array.html#method-i-combinationhttps://ruby-doc.org/core-2.2.0/Array.html#method-i-count

非常感谢。

1 个答案:

答案 0 :(得分:8)

Array#count不是越野车方法,Enumerator#count是:

100000.times.to_a.combination(2).class # => Enumerator

好消息是您遇到的错误是几个月前报告为#14805并随后得到修复的,但是坏消息是,此后没有发布任何新版本的CRuby。因此,要么等待2.5.2、2.4.5等,要么自己编译带有此修复程序的版本。

问题是枚举器的计数器被限制为有符号的32位整数,因此发生了溢出:

max = (1 << 31) - 1 # max value
4999950000 & max    # => 704982704

通过将计数器设为bignum(Ruby的任意精度整数类型,从2.4开始是内部实现细节)来解决此问题,以防其值超出int或目前{{1 }}。