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

时间:2009-02-06 15:10:04

标签: bit-manipulation bit-shift

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

43 个答案:

答案 0 :(得分:53)

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

您还需要轮班以生成哈希值。多项式算术(CRC,Reed-Solomon代码是主流应用)或使用移位。

然而,轮换只是因为它们很方便而且完全表达了作者的意图。如果需要,可以使用乘法模拟所有位移,但这样写起来会更难,可读性更低,有时更慢。

编译器检测到乘法可以减少到一个班次的情况。

答案 1 :(得分:36)

是的,我已经习惯了很多次。在位掩码很常见的嵌入式硬件上,位错误非常重要。当你需要最后一点性能时,它在游戏编程中也很重要。

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

答案 2 :(得分:24)

  • 为枚举创建漂亮的旗帜值(而不是手动输入1,2,4 ......)
  • 从位字段解压缩数据(许多网络协议使用它们)
  • Z曲线遍历
  • Performance hacks

当他们被使用时,我想不出很多情况。它通常是另一种方式 - 存在一些特定问题,并且事实证明采用位操作将产生最佳结果(通常在性能方面 - 时间和/或空间)。

答案 3 :(得分:14)

我一直使用它们的一个地方是为跨平台应用程序转换整数的字节序。当blitting 2D图形时,它们有时也会派上用场(与其他位操作操作符一起使用)。

答案 4 :(得分:8)

我已经使用了几次,但几乎总是用于解析二进制文件格式。

答案 5 :(得分:6)

是的,仍然需要它。

在我的工作中,例如我们开发了通过串口COMx与PLC通信的软件。有必要处理一个字节内的位,我们使用左/右移位和逻辑运算符OR,XOR,和日复一日。

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

这样做效率更高:

Byte B;

B := B XOR 4;

而不是:

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

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

问候。

答案 6 :(得分:6)

位移很快。它们在分割和模数运算之前很久就在CPU指令集中实现。我们中的许多人都使用了位移算术,这种算术在铅笔和纸上都很简单,但在我们的CPU上却无法使用。

例如:

  • 我用过项目的位移 涉及分解大型复合材料 进入他们的主要因素。
  • 我也使用了位移 找到方形和立方根 任意大整数。

答案 7 :(得分:6)

答案 8 :(得分:4)

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

C中也有相当数量。

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

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

例如,如果您有8位,则使用“if(a> 127){...}”检查最高位。然后你左移(或乘以2),用127做“和”(如果设置了最后一位,则做256减法),再做一次。

答案 9 :(得分:3)

位移不能解决高级编程问题,但我们有时必须解决较低级别的问题,而且不必在C中编写单独的库就可以了。那个时候最常用的是我的猜测。

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

答案 10 :(得分:3)

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

答案 11 :(得分:3)

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

答案 12 :(得分:3)

是的,我有。 您可能怀疑它最有可能在低级编程中找到,例如开发设备的驱动程序。但是,我参与了一个C#项目,我必须开发一个从医疗设备接收数据的Web服务。设备存储的所有二进制数据都被编码为SOAP数据包,但二进制数据被压缩和编码。所以要解压缩它,你必须做很多很多的操作。此外,您必须进行大量的移位以解析出任何有用的信息,例如,设备序列号是第二个字节的下半部分或类似的东西。 我也看到.NET(C#)世界中的一些人使用了Bit掩码和Flag属性,我个人从未有过这样做的冲动。

答案 13 :(得分:3)

是的。我必须先编写加密算法,然后才能使用它们。

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

答案 14 :(得分:3)

我在图像压缩/解压缩中使用了很多,其中位图中的位被压缩。使用http://en.wikipedia.org/wiki/Huffman_coding被压缩的东西由不同数量的位组成(它们不是全部字节对齐的),因此在编码或解码它们时需要对它们进行位移。

答案 15 :(得分:3)

将数字从小端转换为大端格式,反之亦然

答案 16 :(得分:2)

比特移位在解读网络游戏协议时被大量使用。协议被设计为尽可能使用一点带宽,因此不是在int32s中传输服务器上的播放器数量,名称等,而是将所有信息打包成尽可能少的字节。现在大多数人使用宽带并不是必需的,但是当它们最初设计时,人们使用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#中)取决于你。

答案 17 :(得分:2)

找出大于或等于给定数字的最接近2的幂:

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

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

答案 18 :(得分:2)

Fast Fourier transform — FFT它的Cooley-Tukey技术需要使用位移操作。

答案 19 :(得分:1)

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

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

答案 20 :(得分:1)

是的,在Java和C#应用程序之间执行二进制通信时,一个是big-endian字节排序,另一个是little-endian(不一定按此顺序)。我创建了一个InputStream类,它可以读取具有不同字节顺序的数字,并使用字节移位来工作。

有时候当你想在4个字节的长整数中放入4个短路时,也就是使用字节移位的情况。我想我多年前就这么做了......

答案 21 :(得分:1)

我在一个嵌入式系统的项目中使用它,它必须读取监视器的EDID数据。 EDID中的某些数据编码如下:

Byte#3:
水平消隐 - 低8位
字节#4:
低半字节:水平消隐 - 高4位
Upper Nibble:别的

答案 22 :(得分:1)

我在游戏中使用它们将一堆标志打包成单个字节/字符以保存到数据卡。像存储解锁状态等等。现在不是很多要求,但可以节省工作。

答案 23 :(得分:1)

我写过的每一个bitblt-er都无法完成,无法左右滑动位。

答案 24 :(得分:1)

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

答案 25 :(得分:1)

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

答案 26 :(得分:1)

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

答案 27 :(得分:0)

位移在嵌入式应用中非常有用,当内存紧张且速度就是一切时。

例如,您可以仅使用加法和位移来执行相同的计算,而不是进行昂贵的乘法运算,这可以节省大量时间:

c := 0
while b != 0
    if (b and 1) != 0
        c := c + a
    shift a left by one
    shift b right by one
return c

答案 28 :(得分:0)

我用它来实现UTF-8和UTF-32之间的转换。

答案 29 :(得分:0)

大多数数据包仍然是位编码的。如果你使用任何类型的低级网络通信,你将不得不玩位。

同时分析包含声音的数据包&amp;视频 - 我相信甚至MP3标签都会使用几个位。

最重要的是,对位操作不熟悉意味着您很可能会错过很多更好的方法来实现某些操作。我的意思是,如果你正在处理50亿个有序对象的存在,那么能够将它们全部放入ram非常舒适地进行即时查找或者每次在文件中查找它之间的区别 - 就像这样的任务我会说,有人称自己是软件工程师而没有操控过程,但是他的工作无能为力。

答案 30 :(得分:0)

我在扑克手评估员中使用过它们。

扑克牌表示为64位无符号整数,手中存在的每张牌都有1位。通过移动和屏蔽的组合,您可以提出诸如“给我所有等级,我手上至少有3张牌”的问题等等。

它的速度相当快,但我已经学会了更快的方法,其中手被表示为一个字节数组。

答案 31 :(得分:0)

不,我从来没有真正使用它们。我认为这些二进制操作对于高级语言有点不赞成。正如有人所说,它总是可以用其他数学表达式来模拟,并且因为它们几乎没有被使用过,所以它们可以在外部库中构建。红宝石或蟒蛇声中的位移对我来说非常奇怪,有点像混合高低级别。

答案 32 :(得分:0)

我曾经在网络项目中使用过位移位。这是一个电子商务应用程序,其中每个产品都有许多可配置的属性。用户可以选择他们想要的属性,UI会更新以提供所选选项的定价和SKU。

不是在数据存储中搜索与用户选项匹配的SKU,而是每个选项组合对应于特定的散列,这实际上是使用位数学创建的数字。我为每个选项允许4位(16种组合),最多5个选项,总共20位。要根据用户的选项计算哈希值,我会遍历每个编号的属性,并添加到哈希值:

for(var i = 0; i < getSku.arguments.length; i++)
{
    index = getAttributeIndex(i, getSku.arguments[i]);
    hash += (index+1) << (4*i);
}

这比循环数百个SKU要快得多,每次比较多达5个值。

答案 33 :(得分:0)

我已经完成了一些新的加密结构的工作,隐藏了同态加法器后面的序列化结构(以及后续更新)。很多哈希还取决于位操作;在他们之间转移。

进行大量的转移,以及令人讨厌的大量操作;所有在Java(诚然,这是一个参考/研究实施)。

还完成了压缩项目(特别是GZIP impl。),你需要经常打包位;无法想象没有&lt;&lt;和&gt;&gt; (或者&gt;&gt;&gt;,如果您使用的是Java)。

基本上,如果您正在使用加密或压缩,那么您很可能需要在某一点进行位移。

答案 34 :(得分:0)

我正在计算机科学专业,我已经使用了位移。

他们很好地存放旗帜,使用哈希等等,人们已经说过了。

我使用一次按位运算来压缩1个小整数(2个字节)值和一个整数中的2个字符。与我的同事的项目相比,这为我节省了很多记忆。

这些操作有时候也很快就会出现算术,例如:当你必须扩展double类型或使用函数来使用mantisses操作浮点数据时(参见浮点算术标准)。

答案 35 :(得分:0)

不确定。处理affinity masks会使用位移。

例如,您可能希望将应用程序限制为使用不超过给定数量的处理器(为了使用每个处理器而花钱) - 您将使用位移来计算关联掩码中的位数吗?

答案 36 :(得分:0)

我在CRC计算中使用它。

答案 37 :(得分:0)

是。特别是在使用控制和状态字节用于硬件驱动程序的仿真器中。控制字节中的每个位都有特殊含义,状态字节中的每个位都有特殊含义。

答案 38 :(得分:0)

我在C#中做了一些改变。应用程序需要规范化语音音频输入,这需要在音频采样级别进行多次数学运算。

答案 39 :(得分:0)

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

答案 40 :(得分:0)

是的,一直都是。像这些用于打包和解压缩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))        

答案 41 :(得分:0)

是的,位移软件一直用于低级嵌入式软件。它也可以用作执行极快数学运算的几乎魔术技巧,看看

http://betterexplained.com/articles/understanding-quakes-fast-inverse-square-root/

答案 42 :(得分:0)

与“低级”设备,eq数字以太网-IO-box或PLC进行通信时也需要进行位移,这通常将各个输入/输出值打包为字节。