加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

如何在按位运算期间截断大整数以模仿Ruby中的JavaScript?

发布时间:2020-12-17 03:17:42 所属栏目:百科 来源:网络整理
导读:我发现在 Ruby中使用整数会导致它们在二进制表示大于32位时与JS不同. a = 144419633058839139324b = 3903086624 JS: a 0; = 1482555392b 0; = -391880672 ruby: a 0 = 144419633058839139324[a].pack('V').unpack('V').first = 1482560508[b].pack('V').un
我发现在 Ruby中使用整数会导致它们在二进制表示大于32位时与JS不同.

a = 144419633058839139324
b = 3903086624

JS:

a >> 0; => 1482555392
b >> 0; => -391880672

ruby:

a >> 0 => 144419633058839139324
[a].pack('V').unpack('V').first => 1482560508
[b].pack('V').unpack('V').first => 3903086624

我的问题是如何转换我的Ruby代码以提供相同的返回值JS?

解决方法

这是一个很好的问题.我做了一些实验,试图弄清楚JavaScript正在做什么操作,但后来我想,“我打赌规范说.”果然,它做到了!

首先我检查了Bitwise Shift Operators部分,我从中学到的是你已经知道的:在进行按位操作之前,JavaScript将其操作数转换为32位整数.为此,它链接到名为ToInt32的“抽象操作”(即由JavaScript引擎实现的算法)的定义.幸运的是,它很容易遵循:

ToInt32: (Signed 32 Bit Integer)

The abstract operation ToInt32 converts its argument to one of 232 integer values in the range -231 through 231?1,inclusive. This abstract operation functions as follows:

  1. Let number be the result of calling 07002 on the input argument. [This just converts non-numeric values like booleans and strings into numbers.]
  2. If number is NaN,+0,?0,+∞,or ?∞,return +0.
  3. Let posInt be sign(number) * floor(abs(number)). [07003 returns -1 if number is negative or 1 if it’s positive.]
  4. Let int32bit be posInt modulo 232; that is,a finite integer value k of Number type with positive sign and less than 232 in magnitude such that the mathematical difference of posInt and k is mathematically an integer multiple of 232.
  5. If int32bit is greater than or equal to 231,return int32bit ? 232,otherwise return int32bit.

我们可以将它直接翻译成Ruby(我将步骤1-5编号为注释):

def to_int32(number)
  # (1)(2)
  begin
    sign = number < 0 ? -1 : 1
    abs = number.abs
    return 0 if abs == 0 || abs == Float::INFINITY
  rescue
    return 0
  end

  pos_int = sign * abs.floor  # (3)
  int_32bit = pos_int % 2**32 # (4)

  # (5)
  return int_32bit - 2**32 if int_32bit >= 2**31
  int_32bit
end

那么,它有效吗?

a = 144419633058839130000
puts to_int32(a)
# => 1482551184

b = 3903086624
puts to_int32(b)
# => -391880672

似乎是合法的!

现在,我确信有更简洁,可能更快的方法来做到这一点,但这应该让你开始.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读