如何访问 ruby​​ 整数的符号位?

zim*_*ies 6 ruby bit-manipulation

我想直接访问 ruby​​ 整数的符号位。

Ruby 允许通过[]操作符访问 int 的位: 1[0] -> 1 2[1] -> 1

我尝试过-1[-1](访问最后一个),但这不起作用。

sok*_*oku 5

您可以通过查看以下文档来理解这一点Fixnum#[]

返回fix的二进制表示形式中的第+n+位,其中fix[0]是最低有效位

https://ruby-doc.org/core-2.2.0/Fixnum.html#method-i-5B-5D

AFixnum不是数组,因此它#[]函数的行为可以(并且确实)与您对数组的期望不同。

解决方案1

要访问最高有效位,您可以使用#bit_length - 1

> a = 5
=> 5
> a[a.bit_length - 1]
=> 1
Run Code Online (Sandbox Code Playgroud)

但是,这排除了负数的符号位,因此要获取符号位,请不要从bit_length

> a = -5
=> 5
> a[a.bit_length]
=> 1
> a = 42
=> 42
> a[a.bit_length]
=> 0
Run Code Online (Sandbox Code Playgroud)

解决方案2

您也可以使用< 0比较:

> a = -5
=> -5
> sign_bit = a < 0 ? 1 : 0
=> 1
Run Code Online (Sandbox Code Playgroud)

解决方案3

首先,让我们阅读以下文档#size

返回 fix 的机器表示形式的字节数。

从函数的实现中我们可以得知,如果存储的数字在 32 位有符号整数的范围内,则将存储为 1。在这种情况下#size返回4. 如果它更大,它将存储在 64 位整数中并#size返回8

然而,并非所有这些位都在使用中。如果您存储数字5(0b101),您的 32 位将被占用

10100000 00000000 00000000 00000000
Run Code Online (Sandbox Code Playgroud)

负数大多数时候存储为 2 的补码(不确定是否适用于 ruby​​),这意味着如果您存储该数字,-5您的 32 位将被占用

11011111 11111111 11111111 11111111
Run Code Online (Sandbox Code Playgroud)

因此,您还可以使用以下代码访问符号位:

x[x.size * 8 - 1]
Run Code Online (Sandbox Code Playgroud)

奖金

如果你好奇为什么5[-1]不抛出异常并且仍然​​返回一个数字,你可以查看源代码Fixnum#[](在前面提到的文档页面上)。

if (i < 0) return INT2FIX(0);
Run Code Online (Sandbox Code Playgroud)

0如果您的索引为负数,则仅返回。