我正在迭代一个相当大的数组的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-combination和https://ruby-doc.org/core-2.2.0/Array.html#method-i-count。
非常感谢。
答案 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 }}。