Emulating int64 overflows in Ruby

邮差的信 提交于 2019-12-20 05:53:36

问题


I'm a long time programmer but new to Ruby. I'm trying to port an algorithm called CheckRevision used for checking integrity of game files before loggin into Battle.net's online gaming service.

The algorithm makes a "hash" of the files with a given formula. Without boring details, it's constantly modifying the values a, b and c which are 64-bit integers, or in the reference implementation I'm porting from, a Java long. My implementation is correct for the first few iterations but when the int64 should wrap around it becomes a BigNum instead.

What's the proper way to restrict a FixNum to 64bit, or should I be using a different type?


回答1:


64-bit integers are represented in Ruby MRI as Bignums internally even on 64-bit platforms in some cases (due to implementation details, Fixnums are only 63 bit long on 64-bit platform sand 31 bit long on 32-bit platforms). Hence, it will be much more faster to use binary "and" operator &:

ruby-1.9.2-p290 :001 > a = 2**128 + 1256231
 => 340282366920938463463374607431769467687 
ruby-1.9.2-p290 :002 > a & (2 ** 64 - 1)
 => 1256231 
ruby-1.9.2-p290 :003 > a & 0xffffffffffffffff
 => 1256231 

The last variant is a bit uglier, but also faster, too, as Ruby MRI lacks constant folders. If you'd do the 002 clause in a loop, it would compute 2**64 - 1 each time).

Ruby MRI is an official ("Matz Ruby Implementation") variant of Ruby, i.e. "plain" Ruby which most of us use. The details I've listed here may or may not apply this way to other implementations, but binary "and" is generally faster or as fast as modulo operator on any platform or language.




回答2:


As long as we're talking unsigned integers, then overflow can be calulated with modulo operator.

irb(main):001:0> a = 2**128 + 1256231
=> 340282366920938463463374607431769467687
irb(main):002:0> a % 2**64
=> 1256231


来源:https://stackoverflow.com/questions/7250216/emulating-int64-overflows-in-ruby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!