无聊翻了下 Medium 中 Ruby 的相关的内容,发现有一篇文章介绍 Ruby 中的按位运算符 bitwise
非常简单,因此翻译在此。
按位运算符并没有把所有的数字 ( Numbers ) 看成是整型 ( integer
),而是把它们看成是一个位 ( bit
) 序列。
这是一个非常有用的概念,因为它把 「 掩码 」的概念带入 「 整型 」( integer ) 中。例如验证 MCQ 的答案是否正确这样。
本文接下来的部分,我们就来了解下 Ruby 中的这个 bitwise
运算符。
十进制转二进制
十进制 应该没啥好解释了吧,我们日常中使用的都是十进制。十进制有十个值,分别是 0
、1
、2
、3
、4
、5
、6
、7
、8
、9
也许你也听说过二进制,也知道它是计算机进行操作的基础。二进制只有两个值 0
和 1
。
二进制中,每个位 ( bit ) 的权重是 2 的倍数。每个值从右到左分配。
- 第一个位 ( 从右往左 ) 的值为
1
- 第二个位的值为 2
- 第三个位的值位 4
- ...以此类推
如果某个位 ( n ) 的值为 1
,则总和的结果需要加上 2n-1 次方的值
我们来看一个范例,了解如何转换二进制的值。在这个范例中,我们将十进制 34
转换为二进制
128 64 32 16 8 4 2 1 | | | | | | | | 0 0 1 0 0 0 1 0
因此,需要将十进制 34 转换为二进制,我们可以从左向右移动,并应用以下规则
- 128 包含在 34 中吗 ? 没有,因此该位的值为 0
- 64 包含在 34 中吗 ? 没有,因此该位的值为 0
- 32 包含在 34 中吗 ? 有,
34-32 = 2
,因此该位为1
,然后使用2
继续向下运算 - 16 包含在 2 中吗 ? 没有,因此该位的值为 0
- 8 包含在 2 中吗 ? 没有,因此该位的值为 0
- 4 包含在 2 中吗 ? 没有,因此该位的值为 0
- 2 包含在 2 中吗 ? 有,
2-2=0
,因此该位的值为0
,然后使用剩余的值0
继续向下运算 - 1 包含在 0 中吗 ? 没有,因此该位的值为 0
综上所述,只有 32 和 2 设置为 1
二进制
正如我们在介绍中看到的那样,按位运算符将整数视为位序列 - 基于二进制 ( base 2 ) 而不是基于十进制 ( base 10 )。
那么,问题来了,如何将整数看成是位序列呢 ?
$> 4.to_s(2) => "100"
Integer#to_s(base = 10)
将一个十进制整数转换为其它进制的数字,参数 base
用于指定要转换到的进制,默认是十进制,如果传递 base=2
,则就是要把整数转换为二进制。
to_s(2)
并不会返回二进制中前面的 0
。它返回一个字符串,包含了以从左到右遇到的第一个 1
个开头的位序列
按位与 「 AND 」 &
操作符
按位与运算其实就是对于位序列中的每个位进行 &
运算。
为了方便你理解这个 &
运算符,我们来演示下如何计算 7 & 5
7 的二进制: 0000 0111 5 的二进制: 0000 0101 128 64 32 16 8 4 2 1 ---------------------- 7: 0 0 0 0 0 1 1 1 & & & & & & & & 5: 0 0 0 0 0 1 0 1 ----------------------- 5: 0 0 0 0 0 1 0 1
因此,7 & 5
的运算结果为 5
如果我们使用 Ruby 中的 &
运算符,结算结果如下
$> 7 & 5 => 5 $> (7 & 5).to_s(2) => "101"
按位或 「 OR 」 |
运算符
按位或运算其实就是对于位序列中的每个位进行 |
运算。
为了方便理解这个 |
运算符,我们来演示下如何计算 7 | 5
7 的二进制: 0000 0111 5 的二进制: 0000 0101 128 64 32 16 8 4 2 1 ---------------------- 7: 0 0 0 0 0 1 1 1 | | | | | | | | 5: 0 0 0 0 0 1 0 1 ---------------------- 7: 0 0 0 0 0 1 1 1
因此,7 | 5
的运算结果为 7
如果我们使用 Ruby 中的 |
运算符,结算结果如下
$> 7 | 5 => 7 $> (7 | 5).to_s(2) => "111"
左移 「 LEFT SHIFT 」 运算符
左移运算符 ( LEFT SHIFT ) <<
将数字的每个位向左移位 n
个位置,右边的空位补 0
为了方便理解这个 <<
运算符,我们来演示下如何计算 7 << 2
7 的二进制: 0000 0111 128 64 32 16 8 4 2 1 ---------------------- 7: 0 0 0 0 0 1 1 1 将每个位左移 2 个位置 ---------------------- 28: 0 0 0 1 1 1 0 0
因此,7 << 2
的运算结果为 28
如果我们使用 Ruby 中的 <<
运算符,结算结果如下
$> 7 << 2 => 28 $> (7 << 2).to_s(2) => "11100"
右移 「 RIGHT SHIFT 」 运算符
左移运算符 ( RIGHT SHIFT ) >>
将数字的每个位向右移位 n
个位置,左边的空位补 0
为了方便理解这个 >>
运算符,我们来演示下如何计算 40 >> 2
40 的二进制: 0010 1000 128 64 32 16 8 4 2 1 ---------------------- 7: 0 0 1 0 1 0 0 0 将每个位右移 2 个位置 ---------------------- 10: 0 0 0 0 1 0 1 0
因此,40 >> 2
的运算结果为 10
如果我们使用 Ruby 中的 >>
运算符,结算结果如下
$> 40 >> 2 => 10 $> (40 >> 2).to_s(2) => "1010"
结束语
按位运算符在 Rails 中并不常用,但当我们需要 MCQ 测试,配置,选项等 「 多选项 」 功能时可以非常方便。
请注意,本文中并没有介绍其它 2 个按位运算符:「按位异或」和 「 按位非 」运算符。我可能会在另一篇文章中介绍它们
源文连接地址为 https://medium.com/@farsi_mehdi/ruby-bitwise-operators-da57763fa368