【问题标题】:Emulating int64 overflows in Ruby在 Ruby 中模拟 int64 溢出
【发布时间】:2011-11-07 04:35:09
【问题描述】:

我是一名资深程序员,但对 Ruby 不熟悉。我正在尝试移植一个名为 CheckRevision 的算法,用于在登录 Battle.net 的在线游戏服务之前检查游戏文件的完整性。

该算法使用给定公式对文件进行“散列”。没有无聊的细节,它会不断地修改值abc,它们是 64 位整数,或者在我移植的参考实现中,Java long。我的实现对于前几次迭代是正确的,但是当 int64 应该环绕它时,它变成了 BigNum。

将 FixNum 限制为 64 位的正确方法是什么,或者我应该使用其他类型吗?

【问题讨论】:

    标签: ruby integer type-conversion


    【解决方案1】:

    只要我们说的是无符号整数,那么溢出就可以用模运算符来计算。

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

    【讨论】:

      【解决方案2】:

      64 位整数在 Ruby MRI 中内部表示为 Bignums,即使在某些情况下在 64 位平台上也是如此(由于实现细节,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”通常更快或与任何平台或语言上的模运算符一样快。

      【讨论】:

      • 我喜欢。如有必要,位推送也应该更容易处理带符号的整数。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-03
      • 2012-02-07
      • 1970-01-01
      • 2020-05-17
      • 2019-02-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多