什么时候适合按位运算

发布于 2024-11-03 03:15:18 字数 246 浏览 6 评论 0原文

我知道按位运算的基本前提(尽管希望有“傻瓜式”解释);但是我不知道什么时候适合使用这种技术。

我的理解是,较旧的 CPU 架构可以比其他操作更快地执行按位运算,因此了解如何使用它们是有利的。鉴于现在情况已不再如此;是否仍然适合执行这些操作?如果适合,出于什么目的以及在什么条件下执行? (我对 C# 上下文特别感兴趣,但很高兴收到一般答案)

I am aware of the basic premise of what bitwise operation are (although would appreciate a "for dummies" explanation); 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. 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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

撩动你心 2024-11-10 03:15:18

位运算是快速检查可能在变量上设置的标志的好方法。

以下示例强调了对 Flag 枚举使用按位运算以及将位填充字段存储到数据库中的好处。然后可以轻松检查位填充字段,看看它是否包含 Flag 枚举中的单个值或值的子集。

示例:

User 数据库表,其中包含名为 Permissiontinyint 字段。该字段使用通过枚举创建的值来填充,该值是 2^n。

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

除了使用按位运算来指定枚举中的值(在编译时完成)之外,您还可以使用枚举来检查数据库中的 Permission 字段是否包含可能值的任何子集。从数据库方面,您可以获得将值填充到单个字段中的能力 - 无需为每个权限设置一列,并且在代码方面,您可以获得检查值的简单方法。

位填充示例(授予 ManageUsers 和 CreateOrders):

Permission userPermissions = Permission.ManageUsers | Permission.CreateOrders;

权限检查示例:

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

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. The bitstuffed field can then easily be checked to see if it contains a single value or subset of values from the Flag enumeration.

Example:

A User database table with a tinyint field called Permission. The field is populated using a value created with the enumeration which values are 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. 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):

Permission userPermissions = Permission.ManageUsers | Permission.CreateOrders;

Example permission check:

public bool HasPermissions(Permission userPermissions, Permission permissionsToCheckFor)
{
    return permissionsToCheckFor == Permission.None ? 
        false : 
        (userPermissions & permissionsToCheckFor) == permissionsToCheckFor;
}
一杯敬自由 2024-11-10 03:15:18

问题不在于按位运算比整数运算更快(尽管它们通常是这样),而在于它们是用于不同目的的不同运算。

从概念上讲,字节、短整型和整数实际上是微小的位数组,按位运算符是布尔数组运算符。如今,在 C# 中,按位运算符主要用于 [Flags] 枚举和 GetHashCode 计算,但使用位数组的方式有无数种。

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. 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.

世界如花海般美丽 2024-11-10 03:15:18

您是对的,仅仅因为语言为您提供了按位运算,您就不应该仅仅因为可以就使用它们。我见过人们在处理简单布尔值时使用按位运算符,但这不是他们的用途。

当处理数据片段与字节边界不对齐的数据结构时,位运算符非常有用。通常,当带宽(或一般内存占用量)非常重要时,就会执行此操作。我从事 RTP 视频流软件的工作,按位运算既用于读取/构造 RTP 传输数据包,也用于读取视频编解码器流,这些流通常使用位而不是字节进行编码。

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.

街道布景 2024-11-10 03:15:18

当空间非常宝贵时,它们在嵌入式控制情况下非常有用。例如,单个字节的数据可以表示 8 个 i/o 位,并且可以使用掩码从 i/o 端口检索感兴趣的位(例如,如果PIN0 = 1、PIN1 = 2、PIN2 = 4 , PIN3 = 8 等等,那么:

  • 要获取 PIN0 的值,我们可以说 PORT0 & PIN0 == 0
  • 来设置 。 >PIN1 为 1,我们可以说 PORT0 |= PIN1
  • 要将 PIN2 设置为 0,我们可以说 PORT0 &= ~PIN2<。 。

除了嵌入式控制之外,我现在很少看到这种方法在 C# 世界中更常见的是每个感兴趣的值都有单独的布尔字段,因为对于现代硬件来说开销确实不是什么大问题 尽管您可能会遇到一两种情况,即使用按位运算将许多此类标志保留在单个变量中)。

对于光标或边界框,还有一个有趣的应用程序是通过异或来添加它们。再次执行相同操作将得到原始图像。

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 (e.g. if PIN0 = 1, PIN1 = 2, PIN2 = 4, PIN3 = 8 and so on, then:

  • To get the value of PIN0, we can say PORT0 & PIN0 == 0.
  • To set PIN1 to 1, we can cay PORT0 |= PIN1.
  • To set PIN2 to 0, we can say 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).

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.

太阳男子 2024-11-10 03:15:18

我发现自己不时使用按位运算符的一种方法是使用二进制掩码生成给定字符串/数组的子集,它是这样的:(对不起,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; 
}

您可能想查看这个富有洞察力的面向竞赛的编程教程: 一点乐趣:比特的乐趣

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)

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文