您是否曾经在实际项目中使用过位移?


83

您是否曾经在实际的编程项目中使用过位移?大多数(如果不是全部)高级语言中都包含移位运算符,但是您何时真正需要使用它们?

Answers:


58

我仍然为那些在硬件中不支持浮点的系统编写代码。在这些系统中,几乎所有算术都需要移位。

另外,您还需要移动以生成哈希。多项式算术(CRC,里德-所罗门代码是主流应用)或也使用移位。

但是,仅使用移位是因为它们很方便,并且可以准确表达作者的意图。您可以根据需要用乘法模拟所有位移,但这将更难编写,可读性较低,有时甚至更慢。

编译器检测可将乘法减少为移位的情况。


37

是的,我已经使用了很多次。对于在位掩码非常常见的嵌入式硬件上,位旋转非常重要。当您需要性能的最后一点时,这在游戏编程中也很重要。

编辑:另外,我经常使用它们来处理位图,例如更改颜色深度或转换RGB <-> BGR。


第二。我做了很多嵌入式编程,移位是常见的操作。
e.James,2009年

此处的RGB <-> BGR转换。
尼尔N

25
  • 为枚举创建漂亮的标记值(而不是手动键入1、2、4 ...)
  • 从位域解压缩数据(许多网络协议都使用它们)
  • Z曲线遍历
  • 性能技巧

而且我无法想到很多情况下都在使用它们。通常情况是相反的-存在一些特定问题,事实证明,采用位运算将产生最佳结果(通常就性能而言-时间和/或空间)。


您可能需要它在ASP.net的Session状态short中的一个integer字段中存储例如两个s,而没有读取和锁定Session来读取两个单独值的开销。另外,节省了在会话中存储两个值的内存开销。
David d C e Freitas

15

我一直使用它们的一个地方是为跨平台应用程序转换整数的字节序。在绘制2D图形时,它们有时也很方便(与其他位操作运算符一起使用)。


其次,为EBCDIC字符集编写一个转换器。不幸的是,这确实是在用高级语言进行低级工作,但是在某些情况下这是必需的。
Michael Meadows,


7

位移很快。它们在除法和模运算之前很久就已在CPU指令集中实现。我们中的许多人都将移位用于算术,这在铅笔和纸上很简单,但在我们的CPU上不可用。

例如:

  • 对于涉及将大型复合材料分解为其主要因素的项目,我已经使用了移位。
  • 我还使用了移位来查找任意大整数的平方根和立方根。

可以请您举一个例子说明如何使用它来查找立方根或平方根吗?我有点不知道如何做到这一点。
Xsmael 2015年

5

是的,仍然需要它。

例如,在我的工作中,我们开发用于通过串行端口COMx与PLC通信的软件。必须处理一个字节内的位,我们每天都使用左移/右移和逻辑运算符OR,XOR,AND。

例如,假设我们需要打开一个字节的第3位(从右到左):

这样做效率更高:

Byte B;

B := B XOR 4;

代替:

Byte B = 0;
String s;  // 0 based index

s = ConvertToBinary (B);
s[5] = "1";
B := ConvertToDecimal (s);

问候。


1
您可能想要添加为什么4与位3有关(从右到左)
HCP

1
为什么是s [5]?不是S [2]吗?
IamIC 2014年

1
B:= B XOR 4; 在这种情况下,要打开特定位,不应该是OR吗?XOR不用于切换吗?stackoverflow.com/questions/47981/...
哈日

4

当我用汇编语言编写代码时,我的代码充满了位移和屏蔽。

在C中也有相当数量的内容。

在JavaScript或服务器语言方面做得还不够。

最好的现代用法可能是逐步浏览表示为1和0的布尔值的打包数组。我曾经总是左移并在汇编中检查符号位,但是在高级语言中,您将其与值进行比较。

例如,如果您有8位,则用“ if(a> 127){...}”检查最高位。然后您左移(或乘以2),对127进行“与”运算(如果最后一位被设置,则对256进行减法运算),然后再次进行运算。


3

我在图像压缩/解压缩中经常使用它们,其中位图中的位被压缩。使用http://en.wikipedia.org/wiki/Huffman_coding,要压缩的内容由各种位数组成(它们并非全都是字节对齐的),因此,在对它们进行编码或解码时需要对它们进行位移位。


3

例如,在密码方法中,在诸如C,C ++的语言上实现。二进制文件,压缩算法和逻辑列表操作-按位操作总是好的=)


3

位移并不能解决高级编程问题,但是有时候我们不得不解决低级问题,而不必编写单独的C语言库来完成操作就很方便。那是我最猜想的用途。

我亲自使用它来编写EBCDIC字符集转换器的编码器。


3

是的,我有。您可能会怀疑,它最有可能在低级编程中找到,例如开发设备的驱动程序。但是,我从事一个C#项目,在那里我必须开发一个从医疗设备接收数据的Web服务。设备存储的所有二进制数据都被编码为SOAP数据包,但是二进制数据已被压缩和编码。因此,要解压缩它,您将不得不进行很多位操作。此外,您还必须进行大量的移位操作以解析出任何有用的信息,例如,设备序列号是第二个字节的下半部分或类似内容。另外,我已经看到.NET(C#)世界中的某些人使用位掩码和标志属性,我个人从来没有这样做的冲动。


3

是的 我必须先编写加密算法,并且肯定会使用它们。

当使用整数等跟踪状态时,它们也很有用。



3

我为计算机外围设备制造商工作。我遇到过,并且不得不实现几乎每天都使用位移的代码。


3

移位在解密网络游戏的协议中被大量使用。这些协议旨在使用尽可能小的带宽,因此,与其在int32中传输服务器上的播放器数量,名称等,不如将所有信息打包成尽可能少的字节。如今,对于大多数人来说,使用宽带并不是真正必要的,但是当他们最初被设计时,人们使用56k调制解调器进行游戏,因此每一点都算在内。

最明显的例子是在Valve的多人游戏中,特别是Counter-Strike,Counter-Strike Source。Quake3协议也相同,但是Unreal并不是那么苗条。

这是一个示例(.NET 1.1)

string data = Encoding.Default.GetString(receive);

if ( data != "" )
{
    // If first byte is 254 then we have multiple packets
    if ( (byte) data[0] == 254 )
    {
        // High order contains count, low order index
        packetCount = ((byte) data[8]) & 15; // indexed from 0
        packetIndex = ((byte) data[8]) >> 4;
        packetCount -= 1;

        packets[packetIndex] = data.Remove(0,9);
    }
    else
    {
        packets[0] = data;

    }
}

当然,您是否将其视为一个真实的项目还是只是一个业余爱好(在C#中)取决于您自己。



2

找出两个大于等于给定数字的最接近的幂:

1 << (int)(ceil(log2(given)))

在不支持任意纹理大小的硬件上进行纹理化时需要。


1

是的,在MPEG2-2传输流解析器中使用了它们。它更容易且可读性更好。


1

我必须编写一个程序来解析DVD光盘上的.ifo文件。这些是说明光盘上有多少标题,章节,菜单等的文件。它们由各种大小和对齐方式的打包位组成。我怀疑许多二进制格式都需要类似的移位。


1

我已经看到将多个标志用作属性参数时使​​用的按位运算符。例如,数字4 = 1 0 0表示设置了三个标志之一。这对于公共API不利,但是在特殊情况下它可以加快处理速度,因为检查位的速度很快。



1

我在游戏中使用它们将一堆标志打包为一个字节/字符,以保存到数据卡中。诸如存储可解锁内容的状态之类的东西。如今不是很多要求,但可以节省工作。


1

我在嵌入式系统项目中使用它,该系统必须读取监视器的EDID数据。EDID中的一些数据是这样编码的:

字节#3:
水平消隐-低8位
字节#4:
下半字节:水平消隐-高4位
上半字节:其他

1

是的,在Java和C#应用程序之间执行二进制通信时,一种是大端字节序,另一种是小端字节序(不一定按此顺序)。我创建了一个InputStream类,该类可以读取具有不同字节顺序的数字,并且使用字节移位才能正常工作。

有时候,当您想在一个长的4个字节中放入4个短裤时,使用字节移位也是一种情况。我想我很多年前做了...


1

另一个非常常见的事情是在提取字节的高半字节时进行4位移位,即

#define HIGH_NIBBLE(byte) (((byte) >> 4) & 0x0F)
#define LOW_NIBBLE(byte)  ( (byte)       & 0x0F)

如果直接使用硬件直接从具有任意位映射的寄存器中获取数据,则尤其如此。
克里斯

0

与“较低级”设备(例如数字以太网IO盒或PLC)通信时,也需要进行位移,这些设备通常将单个输入/输出值打包为字节。



0

是的,一直如此。像这些用于将3space坐标打包到32位整数或从32位整数解包的宏一样:

#define Top_Code(a, b, c)           ((((a) + x) << 20) | (((b) + y) << 10) | ((c) + z))                           
#define From_Top_Code(a, b, c, f)   (a = (((f) >>> 20) - x), b = ((((f) & 0xffc00) >>> 10) - y), c = (((f) & 0x3ff) - z))        

0

我曾经(很多年前)曾经为一个使用Excel Oper结构创建Excel Spreadsheets的项目编写了输出例程。这是一个二进制文件共振峰,需要大量的比特摆动。下面的链接给出了Oper结构Safari Books的风格。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.