简体   繁体   English

何时按位运算是合适的

[英]When are bitwise operations appropriate

I am aware of the basic premise of what bitwise operation are (although would appreciate a "for dummies" explanation); 我知道什么是按位操作的基本前提(虽然会欣赏“for dummies”的解释); however I am unaware of when it is appropriate to use this technique. 但是我不知道何时使用这种技术是合适的。

My understanding is that older CPU architectures could perform bitwise operations faster then other operations and hence it was advantageous to know how to use them. 我的理解是, 较旧的CPU架构可以比其他操作更快地执行按位操作 ,因此知道如何使用它们是有利的。 Given this is no longer the case; 鉴于此情况已不再适用; is it still appropriate to perform them and if so, for what purpose and under what conditions? 是否仍然适合执行它们,如果是,它的目的和条件是什么? (I am specifically interested in the C# context but am happy to receive general answers) (我对C#语境特别感兴趣,但很高兴收到一般答案)

Bitwise operations are a great way to quickly check for a flag that may be set on a variable. 按位运算是快速检查可以在变量上设置的标志的好方法。

The following example highlights the benefits of using bitwise operations on a Flag enumeration as well as storing a bitstuffed field into a database. 下面的示例强调了对Flag枚举使用按位运算以及将bitstuffed字段存储到数据库中的好处。 The bitstuffed field can then easily be checked to see if it contains a single value or subset of values from the Flag enumeration. 然后可以轻松检查bitstuffed字段以查看它是否包含Flag枚举中的单个值或值的子集。

Example: 例:

A User database table with a tinyint field called Permission . 具有名为Permissiontinyint字段的User数据库表。 The field is populated using a value created with the enumeration which values are 2^n. 使用通过枚举创建的值填充该字段,其值为2 ^ n。

[Flags]
public enum Permission : byte
{
    None = 0,
    ManageUsers = 1 << 0,
    CreateOrders = 1 << 1,
    PurchaseEquipment = 1 << 2,
    CancelOrders = 1 << 3,
}

Apart from bitwise operations being used to specify values in the enumeration (done at compile time), you can use the enumeration to check if the Permission field in the database contains any subset of the possible values. 除了用于指定枚举中的值的按位运算(在编译时完成)之外,您还可以使用枚举来检查数据库中的Permission字段是否包含可能值的任何子集。 From the database side you gain the ability to stuff values into a single field - eliminating the need to have a column for each permission and in the code side you gain an easy way to check for a value. 从数据库方面,您可以将值填充到单个字段中 - 无需为每个权限创建列,并且在代码方面,您可以轻松地检查值。

Example bitstuffing (Grant ManageUsers and CreateOrders): bitstuffing示例(Grant ManageUsers和CreateOrders):

Permission userPermissions = Permission.ManageUsers | Permission.CreateOrders;

Example permission check: 权限检查示例:

public bool HasPermissions(Permission userPermissions, Permission permissionsToCheckFor)
{
    return permissionsToCheckFor == Permission.None ? 
        false : 
        (userPermissions & permissionsToCheckFor) == permissionsToCheckFor;
}

The issue is not so much that bitwise operations are faster than integer operation (although they usually are), it's that they are different operations for different purposes. 问题不在于按位运算比整数运算更快(尽管它们通常是这样),而是它们是用于不同目的的不同运算。

Conceptually bytes and shorts and ints are really tiny arrays of bits and bitwise operators are boolean array operators. 从概念上讲字节和短裤和int为位和位运算符的真正小数组布尔数组运算符。 In C# nowadays bitwise operators are mostly used for [Flags] enumerations and in calculations for GetHashCode but there are endless ways that arrays of bits can be used. 在C#中,现在按位运算符主要用于[Flags]枚举和GetHashCode计算,但是有无数种方法可以使用位数组。

You are correct that just because language gives you bitwise operation, you should not use them just because you can. 你是正确的,因为语言给你按位操作,你不应该只是因为你可以使用它们。 I've seen people use bitwise operators when working with simple booleans and that's not what they are for. 我看到人们在使用简单的布尔值时使用按位运算符,而这不是它们的用途。

Bitwise operators are useful when working with data structures where pieces of data are not aligned with byte boundary. 在处理数据结构未与字节边界对齐的数据结构时,按位运算符非常有用。 Generally, this is done when bandwidth (or general memory footprint) is very important. 通常,这是在带宽(或通用内存占用量)非常重要时完成的。 I work on RTP video streaming software and bitwise operations are used both in reading/constructing RTP transmission packets as well as for reading video codec streams, which are often encoded using bits, not bytes. 我致力于RTP视频流软件,并且按位操作用于读取/构建RTP传输分组以及用于读取视频编解码器流,其通常使用比特而不是字节来编码。

They can be really useful in embedded control situations when space is at a premium. 当空间非常宝贵时,它们在嵌入式控制情况下非常有用。 For example, a single byte of data can represent 8 i/o bits, and masks can be used to retrieve the bits of interest from an i/o port (eg if PIN0 = 1, PIN1 = 2, PIN2 = 4, PIN3 = 8 and so on, then: 例如,单个字节的数据可以表示8个i / o位,并且掩码可以用于从i / o端口检索感兴趣的位(例如,如果PIN0 = 1, PIN1 = 2, PIN2 = 4, PIN3 = 8等等,然后:

  • To get the value of PIN0 , we can say PORT0 & PIN0 == 0 . 要获得PIN0的值,我们可以说PORT0 & PIN0 == 0
  • To set PIN1 to 1, we can cay PORT0 |= PIN1 . 要将PIN1设置为1,我们可以输入PORT0 |= PIN1
  • To set PIN2 to 0, we can say PORT0 &= ~PIN2 . 要将PIN2设置为0,我们可以说PORT0 &= ~PIN2

Away from embedded control, I rarely see this approached used these days. 远离嵌入式控制,我很少看到这些日子使用过。 In the C# world it's much more common to see individual boolean fields for each value of interest, since the overhead is really not a big deal with modern hardware (though you may run into a case or two where bitwise operations are used to keep many such flags in a single variable). 在C#世界中,为每个感兴趣的值看到单独的布尔字段更为常见,因为开销对于现代硬件来说真的不是很大(尽管你可能遇到一个或两个案例,其中使用按位运算来保持许多这样的单个变量中的标志)。

There is also an interesting application in graphics. 图形中还有一个有趣的应用。 A neat trick for cursors or bounding boxes is to add them by XOR'ing the cursor shape with the image below. 游标或边界框的一个巧妙技巧是通过将光标形状与下面的图像进行异或来添加它们。 Performing the same operation again will result in the original image. 再次执行相同的操作将产生原始图像。

One way I find myself using bitwise operators from time to time is to generate subsets of a given string/array using a binary mask, it goes like this: (sorry, c++ code) 我发现自己不时使用按位运算符的一种方法是使用二进制掩码生成给定字符串/数组的子集,它是这样的:(抱歉,c ++代码)

string s = "abcde";
for(int i = 0; i < 1<<s.size(); i++) {
  string tmp;
  for(int j = 0; j < s.size(); j++) if(i & 1<<j) tmp.push_back(s[j]);
  cout<<tmp<<endl; 
}

You may want to check this insightful contests-oriented programming tutorial: A bit of fun: fun with bits 您可能想要查看这个富有洞察力的面向竞赛的编程教程: 有点乐趣:有趣的比特

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM