除了快速数学之外,还有什么充分的理由使用位移位吗?
我了解按位运算以及它们如何用于不同的目的,例如权限。但是,我似乎不明白位移运算符有什么用。我理解它们是如何工作的,但我想不出任何可能想要使用它们的场景,除非我想做一些非常快速的乘法或除法。使用位移位还有其他原因吗?
I understand bitwise operations and how they might be useful for different purposes, e.g. permissions. However, I don't seem to understand what use the bit shift operators are. I understand how they work, but I can't think of any scenarios where I might want to use them unless I want to do some really quick multiplication or division. Are there any other reasons to use bit-shifting?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
原因有很多,以下是一些:
由于这些和其他原因,大多数处理器都具有位移和/或旋转指令以及其他逻辑指令(和/或/异或/非)。
从历史上看,乘法和除法的速度要慢得多,因为它们是更复杂的运算,而有些 CPU 根本没有这些运算。
另请参阅此处:
您是否曾经在实际中使用过位移位项目?
There are many reasons, here are some:
For those and other reasons most processors have bit shift and/or rotation instructions as well as other logic instructions (and/or/xor/not).
Historically multiplication and division were significantly slower as they are more complex operations and some CPUs didn't have those at all.
Also see here:
Have you ever had to use bit shifting in real projects?
正如您所指出的,左移与乘以二是一样的。至少当我们谈论无符号数量时是这样。有符号量“左移”的含义……取决于语言。
对于现代编译器,编写“i = x*2;”实际上没有区别。且“i = x << 1;”编译器将生成最有效的代码。所以从这个意义上说,没有理由更喜欢移位而不是乘法。
一些算法的工作原理是将数量左移一位,然后将低位设置为 0 或 1。一些简单的压缩算法就是这样工作的。例如,如果您的累计值在变量 x 中,当前值(0 或 1)在 y 中,那么编写“x = (x << 1) | y”更有意义,而不是“x = (x * 2) + y”。两者都做同样的事情,但第一个在符号上更正确。您不必想:“哦,对了,乘以二与左移相同。”
另外,当您谈论移位位的算法时,向左或向右移动特定位数比计算要乘或除的 2 的倍数更方便。
因此,虽然移位而不是乘法通常不会带来性能优势(至少在使用高级语言时不会),但有时,具有移位能力会使您所做的事情更容易理解。
As you indicate, a left shift is the same thing as a multiplication by two. At least it is when we're talking about unsigned quantities. The meaning of a "left shift" of a signed quantity is ... language dependent.
With modern compilers, there's really no difference between writing "i = x*2;" and "i = x << 1;" The compiler will generate the most efficient code. So in that sense there's no reason to prefer shift over multiply.
Some algorithms work by shifting a quantity left by one bit and then setting the low bit to either 0 or 1. Some simple compression algorithms work this way. For example, if your accumulated value is in the variable x, and the current value (0 or 1) is in y, then it makes more sense to write "x = (x << 1) | y", rather than "x = (x * 2) + y". Both do the same thing, but the first is more notationally correct. You don't have to think, "oh, right, multiply by two is the same as a left shift."
Also, when you're talking about algorithms that shift bits, it's more convenient to shift left or right by a particular number of bits than to figure out what multiple of 2 you want to multiply or divide by.
So, whereas there's typically no performance benefit to shifting rather than multiplying--at least not when working with high level languages--there are times when having the ability to shift makes what you're doing more easily understood.
除了数值计算之外,还有很多地方经常使用移位运算。例如,Bitboard 是棋盘游戏中常用的棋盘表示数据结构。一些最强大的国际象棋引擎使用这种数据结构主要是为了速度和轻松地移动生成和评估。这些程序大量使用位运算,并且位移位运算专门用于许多上下文中 - 例如查找位掩码、在棋盘上生成新的移动、快速计算对数等。甚至可以进行非常高级的数值计算通过巧妙地使用位运算来优雅地完成。查看此网站了解位旋转黑客 - 很多算法都使用移位运算符。移位操作经常用于设备驱动程序编程、编解码器开发、嵌入式系统编程等。
There are lot of places where bit shift operations are regularly used outside of their usage in numerical computations. For example, Bitboard is a data structure that is commonly used in board games for board representation. Some of the strongest chess engines use this data structure mainly for speed and ease of move generation and evaluation. These programs use bit operations heavily and bit-shift operations specifically are used in a lot of contexts - such as finding bit masks, generating new moves on the board, computing logarithm very quickly, etc. There are even very advanced numerical computations that can be done elegantly by clever use of bit operations. Check out this site for bit twiddling hacks - a lot of those algorithms use shift operators. Bit shift operations are regularly used in device driver programming, codec development, embedded systems programming and so on.
移位允许访问变量内的特定位。表达式
(n >> p) & ((1 << m) - 1)
检索变量n
的m
位部分,偏移量为p
代码> 从右侧开始位。这允许您的程序使用不是 8 位倍数的整数,这对于数据压缩很有用。
例如,我在我的 Netflix 奖品 程序中使用它来打包记录(22 位用户 ID + 15-位电影 ID + 12 位日期 + 3 位评级)转换为
uint64_t
(还有 12 位备用)。一个非常常见的特殊情况是将 8 个
bool
变量打包到每个字节中。 (Unix 文件权限、黑白位图、CPU 标志寄存器等)此外,UTF-8,这是一种非常流行的字符编码。 Unicode 字符通过将其位分布在 1、2、3 或 4 个字节中来表示。
Shifting allows accessing specific bits within a variable. The expression
(n >> p) & ((1 << m) - 1)
retrieves anm
-bit portion of the variablen
with an offset ofp
bits from the right.This allows your program to use integers that aren't multiples of 8 bits, which is useful for data compression.
For example, I used it in my Netflix Prize programs to pack records (22-bit user ID + 15-bit movie ID + 12-bit date + 3-bit rating) into a
uint64_t
(with 12 bits to spare).A very common special case is to pack 8
bool
variables into each byte. (Unix file permissions, black-and-white bitmaps, CPU flags registers, etc.)Also, bit manipulation is used in UTF-8, which is a very popular character encoding. Unicode characters are represented by distributing their bits across 1, 2, 3, or 4 bytes.