1
1793
位移位运算符完全按照其名称执行。它们移位位。以下是对不同轮班操作员的简要介绍(或不那么简要)。
所有这些运算符都可以应用于整数值(
注意
C和C++不区分右移位算子
. 它们只提供
(在所有主流的C和C++实现中,包括GCC和CLAN/LLVM,
左移(<<)
将此位模式向左移动一个位置(
如您所见,数字向左移动了一个位置,右侧的最后一个数字用零填充。您可能还注意到向左移动相当于乘以2的幂。所以
非圆移位
不
循环移位。将该值向左移动一个位置(
322225472中的结果:
逻辑右移与左移相反。它们只是向右移动,而不是向左移动位。例如,移动数字12:
向右移动一个位置(
我们看到右移相当于除以2的幂。 然而,移位不能回收“丢失”的位。例如,如果我们改变这种模式:
向左4个位置(
一旦我们失去了一些东西,我们就无法找回我们原来的价值。 算术右移与逻辑右移完全相同,不同的是它不是用零填充,而是用最高有效位填充。这是因为最重要的位是 签名 位,或区分正数和负数的位。通过使用最高有效位填充,算术右移保持符号不变。 例如,如果我们将此位模式解释为负数:
我们的电话号码是2147483552。使用算术移位(-2147483552>>4)将其向右移动4个位置,将得到:
或致电134217722。
|
2
217
假设我们只有一个字节:
应用单个左位移位可使我们:
最左边的零被移出字节,新的零被追加到字节的右端。 钻头不会翻转;它们被丢弃了。这意味着如果你左移1101100,然后右移它,你不会得到同样的结果回来。 向左移动N等于乘以2 N 右移N是(如果您正在使用 ones' complement )等于除以2 N 如果您使用的是2的幂,那么位移位可以用于非常快的乘法和除法。几乎所有低级图形例程都使用位移位。 例如,在过去,我们在游戏中使用了13h模式(320x200 256色)。在模式13h中,视频内存按像素顺序排列。这意味着要计算像素的位置,可以使用以下数学:
现在,回到那个时代,速度是至关重要的,所以我们将使用位移位来完成这个操作。 然而,320不是二的幂,所以为了解决这个问题,我们必须找出什么是二的幂,加起来就是320:
现在我们可以将其转换为左移位:
最终结果如下:
总计:在任何有这些计时的古代CPU上都有28个周期。 Vrs
在同一个古老的CPU上运行12个周期。 是的,我们会努力减少16个CPU周期。 在32位或64位模式下,两个版本都会变得更短更快。像Intel Skylake这样的现代无序执行CPU(请参阅 http://agner.org/optimize/ )具有非常快的硬件乘法(低延迟和高吞吐量),因此增益要小得多。AMD推土机系列有点慢,尤其是64位乘法器。在Intel CPU和AMD Ryzen上,两次移位的延迟稍低,但指令数比乘法多(这可能导致吞吐量降低):
vs。
编译器将为您做到这一点:看看如何
GCC, Clang, and Microsoft Visual C++ all use shift+lea when optimizing
这里要注意的最有趣的事情是
x86 has a shift-and-add instruction (
好吧,回到现代。。。现在更有用的方法是使用位移位在16位整数中存储两个8位值。例如,在C#中:
|
3
108
图形编程中的一个简单实例是,16位像素表示如下:
要获得绿色值,请执行以下操作:
为了获得仅绿色的值,即从偏移量5开始到10结束(即6位长),您需要使用(位)掩码,当对整个16位像素应用该掩码时,将仅产生我们感兴趣的位。
适当的掩码为0x7E0,二进制为00000 111111 00000(十进制为2016)。
应用掩码后,您将得到一个16位的数字,实际上它只是一个11位的数字,因为它的MSB位于第11位。绿色实际上只有6位长,所以我们需要使用右移(11-6=5)来缩小它,因此使用5作为偏移量(
同样常见的是使用位移位进行2次幂的快速乘法和除法:
|
4
55
位掩蔽&移动位移位通常用于低级图形编程。例如,在32位字中编码的给定像素颜色值。
为了更好地理解,使用相同的二进制值标记什么部分代表什么颜色部分。
比如说,我们想要得到这个像素颜色的绿色值。我们可以很容易地通过 掩蔽 和 .
合乎逻辑的
这通常用于编码或解码图像格式,如
|
5
28
一个问题是以下内容取决于实现(根据ANSI标准):
x现在可以是127(01111111)或仍然是-1(11111111)。 实际上,通常是后者。 |
6
25
我只写技巧和技巧。它可能在测试和考试中有用。
|
7
8
例如:
等于2。您可能会认为将位向右移动65次会使所有内容归零,但实际上相当于:
|
8
5
按位运算符用于执行位级操作或以不同方式操纵位。按位运算速度更快,有时用于提高程序的效率。 基本上,按位运算符可以应用于整数类型: 长的 , int 短的 , 烧焦 和 字节 位移位运算符它们分为两类:左移和右移。
,此处3的二进制表示为0…0011(考虑到32位系统),因此当它移位一次时,前导零被忽略/丢失,其余31位全部向左移位。最后加上零。所以它变成了0…0110,这个数字的十进制表示是6。
输出:-2 在java中,负数表示为2的补码。所以,-1表示为2^32-1,相当于1…11(考虑32位系统)。当移位一次时,前导位被忽略/丢失,其余31位向左移位,最后加零。所以它变成,11…10,它的十进制等价物是-2。 所以,我想你已经对左移位及其工作原理有了足够的了解。
产出:8 或者有一个 为了找出以下代码的输出:为了概括这一点,我们可以说,x>&燃气轮机;y=地板(x/pow(2,y))。考虑上面的例子,x=35,y=2,因此,35/2 ^ 2=8.75,如果取楼层值,则答案是8。
输出:
但是记住一件事,这个技巧适用于y的小值,如果你取y的大值,它会给你错误的输出。
,正如我上面解释的,编译器将负值存储为2的补码。因此,-10表示为2^32-10,并且考虑到32位系统11…0110,采用二进制表示。当我们移位/移动一次时,前31个前导位在右侧移位,低阶位丢失/忽略。所以,它变成11…0011,这个数字的十进制表示是-5(我怎么知道数字的符号?因为前导位是1)。 有趣的是,如果将-1右移,结果始终保持为-1,因为符号扩展在高阶位中不断引入更多的1。
输出:2147483647 ,因为-2在32位系统中表示为11…10。当我们逐位移位时,前31个前导位向右移动/移位,低阶位丢失/忽略,零添加到前导位。因此,它变成011…1111(2^31-1),其十进制等价物为2147483647。 |
9
4
Ravi Prakash's answer 在Python中。
|
10
2
每个操作数必须具有整数或枚举类型。编译器对操作数执行整数提升,然后右操作数转换为int类型。结果与左操作数的类型相同(算术转换后)。 右操作数的值不应为负值或大于或等于正在移位的表达式的位宽度。这种值的位移位结果是不可预测的。
这个<&书信电报;运算符用零填充空位。例如,如果left_op的值为4019,则left_op的位模式(16位格式)为:
表达式left_op>&燃气轮机;3收益率:
|
11
-3
请注意,Windows平台上只有32位版本的PHP可用。
当然,如果使用64位版本的PHP(Unix),应该避免移位超过63位。但是,例如,MySQL使用64位BIGINT,因此不应该存在任何兼容性问题。 更新:从PHP7窗口,PHP构建最终能够使用完整的64位整数: 整数的大小取决于平台,尽管通常的最大值约为20亿(即32位有符号)。64位平台的最大值通常约为9E18,但在PHP7之前的Windows上除外,该值始终为32位。 |
John Proctor · C中位的掩蔽范围 6 年前 |
Jakey · C枚举定义中的按位移位有什么作用? 6 年前 |
Areg Sarvazyan · 从无符号int中提取位的函数 6 年前 |
goodvibration · 实施安全左移 7 年前 |
AesSedai101 · Kotlin'shl'不工作 7 年前 |
Sam Hammamy · 如何在位运算中选择正确的左移位? 7 年前 |