我是一名资深程序员,但对 Ruby 还是个新手。我正在尝试移植一种名为 CheckRevision 的算法,用于在登录 Battle.net 的在线游戏服务之前检查游戏文件的完整性。
该算法使用给定的公式对文件进行“散列”。没有无聊的细节,它不断修改值 a
、b
和 c
,它们是 64 位整数,或者在我的引用实现中从 Java long
移植。我的实现对于前几次迭代是正确的,但是当 int64 应该环绕它时,它变成了 BigNum。
将 FixNum 限制为 64 位的正确方法是什么,或者我应该使用不同的类型?
最佳答案
在某些情况下,即使在 64 位平台上,64 位整数在 Ruby MRI 内部也表示为 Bignums(由于实现细节,Fixnums 在 64 位平台上只有 63 位长,在 32 位平台上只有 31 位长).因此,使用二进制“与”运算符 &
会更快:
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
最后一个变体有点丑陋,但也更快,因为 Ruby MRI 缺少常量文件夹。如果您在循环中执行 002
子句,它每次都会计算 2**64 - 1
。
Ruby MRI 是 Ruby 的官方(“Matz Ruby 实现”)变体,即我们大多数人使用的“普通”Ruby。我在此处列出的详细信息可能会也可能不会以这种方式应用于其他实现,但二进制“and”通常比任何平台或语言上的模运算符更快或一样快。
关于ruby - 在 Ruby 中模拟 int64 溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31319709/