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

knu*_*gie 2 ruby arrays

我正在迭代一个相当大的数组的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
Run Code Online (Sandbox Code Playgroud)

我用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.

非常感谢.

cre*_*mno 8

Array#count不是有缺陷的方法,Enumerator#count是:

100000.times.to_a.combination(2).class # => Enumerator
Run Code Online (Sandbox Code Playgroud)

好消息是您几个月前报告的错误是#14805并随后修复,但坏消息是从那以后没有新版本的CRuby发布.所以要么等待2.5.2,2.4.5等,要么自己编译修复版本.

问题是枚举器的计数器仅限于带符号的32位整数,因此发生了溢出:

max = (1 << 31) - 1 # max value
4999950000 & max    # => 704982704
Run Code Online (Sandbox Code Playgroud)

通过使计数器成为bignum(Ruby的任意精度整数类型,因为2.4是一个内部实现细节)来修复它,以防它的值超出an int或者现在的范围unsigned long.