按位运算及用法

2024-12-02 08:41:00
admin
原创
167
摘要:问题描述:考虑以下代码:x = 1 # 0001 x << 2 # Shift left 2 bits: 0100 # Result: 4 x | 2 # Bitwise OR: 0011 # Result: 3 x & 1 # B...

问题描述:

考虑以下代码:

x = 1        # 0001
x << 2       # Shift left 2 bits: 0100
# Result: 4

x | 2        # Bitwise OR: 0011
# Result: 3

x & 1        # Bitwise AND: 0001
# Result: 1

我可以理解 Python(和其他语言)中的算术运算符,但我不太理解“按位”运算符。在上面的例子中(来自一本 Python 书),我理解左移,但不理解其他两个。

另外,位运算符实际上有什么用处?我希望能够举一些例子。


解决方案 1:

按位运算符是针对多位值进行操作的运算符,但概念上每次只对一位进行操作。

  • AND仅当其两个输入都为 1 时才为 1,否则为 0。

  • OR若其一个或两个输入为 1,则为 1,否则为 0。

  • XOR仅当其输入中恰好有一个为 1 时才为1,否则为 0。

  • NOT仅当其输入为 0 时才为 1,否则为 0。

这些通常最好以真值表的形式显示。输入可能性位于左上方,结果位是输入交叉点处显示的四个值之一(对于 NOT 的情况,结果位是两个,因为它只有一个输入)。

AND | 0 1     OR | 0 1     XOR | 0 1    NOT | 0 1
----+-----    ---+----     ----+----    ----+----
 0  | 0 0      0 | 0 1       0 | 0 1        | 1 0
 1  | 0 1      1 | 1 1       1 | 1 0

一个例子是如果你只想要整数的低 4 位,你可以将它与 15(二进制 1111)进行 AND 运算,因此:

    201: 1100 1001
AND  15: 0000 1111
------------------
 IS   9  0000 1001

在这种情况下,15 中的零位实际上充当了过滤器的角色,强制结果中的位也为零。

此外,>><<通常作为按位运算符包含在内,它们分别将值向右和向左“移动”一定数量的位,丢弃向其移动的一端滚动的位,并在另一端输入零位。

例如:

1001 0101 >> 2 gives 0010 0101
1111 1111 << 4 gives 1111 0000

请注意,Python 中的左移并不常见,因为它不使用固定宽度,位会被丢弃 - 虽然许多语言使用基于数据类型的固定宽度,但 Python 只是扩展宽度以适应额外的位。为了在 Python 中获得丢弃行为,您可以在左移后按位操作,and例如在 8 位值中左移四位:

bits8 = (bits8 << 4) & 255

考虑到这一点,位运算符的另一个示例是,如果您有两个 4 位值要打包成一个 8 位值,则可以使用所有三个运算符(left-shiftandor):

packed_val = ((val1 & 15) << 4) | (val2 & 15)
  • & 15操作将确保两个值都只有低 4 位。

  • << 4是 4 位左移,移动val1到 8 位值的前 4 位。

  • 简单|地将这两者结合在一起。

如果val1为 7 且val2为 4:

                val1            val2
                ====            ====
 & 15 (and)   xxxx-0111       xxxx-0100  & 15
 << 4 (left)  0111-0000           |
                  |               |
                  +-------+-------+
                          |
| (or)                0111-0100

解决方案 2:

一种典型用法:

|用于将某位设置为 1

&用于测试或清除某个位

  • 设置一个位(其中 n 是位数,0 是最低有效位):

unsigned char a |= (1 << n);

  • 清楚一点:

unsigned char b &= ~(1 << n);

  • 稍微切换一下:

unsigned char c ^= (1 << n);

  • 测试一下:

unsigned char e = d & (1 << n);

以你的列表为例:

x | 2用于将位 1 设置为x1

x & 1用于测试的位 0x是 1 还是 0

解决方案 3:

位运算符实际上有什么用处?我希望能够举一些例子。

按位运算最常见的用途之一是解析十六进制颜色。

例如,这里有一个Python函数,它接受一个字符串#FF09BE并返回其红色、绿色和蓝色值的元组。

def hexToRgb(value):
    # Convert string to hexadecimal number (base 16)
    num = (int(value.lstrip("#"), 16))

    # Shift 16 bits to the right, and then binary AND to obtain 8 bits representing red
    r = ((num >> 16) & 0xFF)

    # Shift 8 bits to the right, and then binary AND to obtain 8 bits representing green
    g = ((num >> 8) & 0xFF)

    # Simply binary AND to obtain 8 bits representing blue
    b = (num & 0xFF)
    return (r, g, b)

我知道有更有效的方法来实现这一点,但我相信这是一个非常简洁的例子,说明了移位和按位布尔运算。

解决方案 4:

我认为问题的第二部分:

另外,位运算符实际上有什么用处?我希望能够举一些例子。

仅部分解决。以上是我对此事的看法。

位运算在编程语言中扮演着非常重要的角色,在很多应用中,几乎所有的低级计算都要用到这种运算。

在所有需要在两个节点之间发送数据的应用程序中,例如:

  • 计算机网络;

  • 电信应用(手机、卫星通信等)。

在通信的较低层,数据通常以所谓的的形式发送。帧只是通过物理通道发送的字节串。这些帧通常包含实际数据以及一些其他字段(以字节编码),这些字段是所谓的报的一部分。报头通常包含对与通信状态相关的一些信息进行编码的字节(例如,使用标志(位))、帧计数器、校正和错误检测码等。要获取帧中传输的数据并构建帧以发送数据,您将需要进行一些按位操作。

一般来说,在处理这类应用程序时,可以使用 API,因此您不必处理所有这些细节。例如,所有现代编程语言都提供套接字连接库,因此您实际上不需要构建 TCP/IP 通信框架。但想想那些为您编写这些 API 的优秀人员,他们肯定必须处理框架构建;使用各种按位运算在低级和高级通信之间来回切换。

举一个具体的例子,假设有人给你一个文件,其中包含电信硬件直接捕获的原始数据。在这种情况下,为了找到帧,你需要读取文件中的原始字节,并尝试通过逐位扫描数据来找到某种同步字。识别同步字后,你需要获取实际帧,并在必要时对它们进行 SHIFT(这只是故事的开始)以获取正在传输的实际数据。

另一种非常不同的低级应用是当您需要使用某些(有点古老的)端口(例如并行端口和串行端口)来控制硬件时。这些端口通过设置一些字节来控制,并且这些字节的每个位对于该端口都有特定的含义(就指令而言)(例如,请参阅http://en.wikipedia.org/wiki/Parallel_port)。如果您想构建使用该硬件执行某些操作的软件,则需要按位操作将要执行的指令转换为端口可以理解的字节。

例如,如果您有一些物理按钮连接到并行端口来控制其他设备,您可以在软应用程序中找到以下代码行:

read = ((read ^ 0x80) >> 4) & 0x0f; 

希望这能有所帮助。

解决方案 5:

我没有看到上面提到这一点,但您也会看到有些人使用左移和右移进行算术运算。左移 x 相当于乘以 2^x(只要不溢出),右移相当于除以 2^x。

最近我看到有人使用 x << 1 和 x >> 1 来加倍和减半,虽然我不确定他们是否只是想耍小聪明,或者是否真的比普通运算符有明显的优势。

解决方案 6:

我希望这能澄清以下两个问题:

x | 2

0001 //x
0010 //2

0011 //result = 3

x & 1

0001 //x
0001 //1

0001 //result = 1

解决方案 7:

将 0 视为假,1 视为真。然后按位与(&) 和或(|) 的工作方式与常规与和或一样,只是它们一次处理值中的所有位。通常,如果您有 30 个可设置的选项(比如窗口上的绘制样式),您会看到它们用于标志,您不想传入 30 个单独的布尔值来设置或取消设置每个选项,因此您可以使用 | 将选项组合成一个值,然后使用 & 检查每个选项是否设置了。OpenGL 大量使用这种标志传递样式。由于每个位都是一个单独的标志,您可以获得 2 的幂的标志值(即只有一位设置的数字)1(2^0) 2(2^1) 4(2^2) 8(2^3),2 的幂告诉您如果标志打开,哪个位被设置了。

还要注意 2 = 10,所以 x|2 是 110(6) 而不是 111(7) 如果没有位重叠(在这种情况下是正确的)| 就像加法一样。

解决方案 8:

可以使用数学运算来组合集合。

  • 并集运算符|将两个集合合并起来,形成一个包含任一集合中的项的新集合。

  • 交集运算符&仅获取两者中的项目。

  • 差分运算符-获取第一个集合中的项目,但不获取第二个集合中的项目。

  • 对称差分运算符^可以获取任一集合中的项,但不能同时获取两者中的项。

自己尝试一下:

first = {1, 2, 3, 4, 5, 6}
second = {4, 5, 6, 7, 8, 9}

print(first | second)

print(first & second)

print(first - second)

print(second - first)

print(first ^ second)

结果:

{1, 2, 3, 4, 5, 6, 7, 8, 9}

{4, 5, 6}

{1, 2, 3}

{8, 9, 7}

{1, 2, 3, 7, 8, 9}

解决方案 9:

此示例将向您展示所有四个 2 位值的操作:

10 | 12

1010 #decimal 10
1100 #decimal 12

1110 #result = 14

10 & 12

1010 #decimal 10
1100 #decimal 12

1000 #result = 8

以下是一个使用示例:

x = raw_input('Enter a number:')
print 'x is %s.' % ('even', 'odd')[x&1]

解决方案 10:

另一个常见用例是操作/测试文件权限。请参阅 Python stat 模块:http://docs.python.org/library/stat.html

例如,要将文件的权限与所需的权限集进行比较,您可以执行以下操作:

import os
import stat

#Get the actual mode of a file
mode = os.stat('file.txt').st_mode

#File should be a regular file, readable and writable by its owner
#Each permission value has a single 'on' bit.  Use bitwise or to combine 
#them.
desired_mode = stat.S_IFREG|stat.S_IRUSR|stat.S_IWUSR

#check for exact match:
mode == desired_mode
#check for at least one bit matching:
bool(mode & desired_mode)
#check for at least one bit 'on' in one, and not in the other:
bool(mode ^ desired_mode)
#check that all bits from desired_mode are set in mode, but I don't care about 
# other bits.
not bool((mode^desired_mode)&desired_mode)

我将结果转换为布尔值,因为我只关心真假,但打印出每个结果的 bin() 值是值得的练习。

解决方案 11:

在科学计算中,整数的位表示通常用于表示真假信息数组,因为按位运算比遍历布尔数组要快得多。(高级语言可能会使用位数组的概念。)

一个很好的、相当简单的例子是 Nim 游戏的通用解决方案。查看Wikipedia 页面上的Python代码。它大量使用了按位排他或。^

解决方案 12:

可能有更好的方法来找到数组元素在两个值之间的位置,但是正如这个例子所示,&在这里有效,而and无效。

import numpy as np
a=np.array([1.2, 2.3, 3.4])
np.where((a>2) and (a<3))      
#Result: Value Error
np.where((a>2) & (a<3))
#Result: (array([1]),)

解决方案 13:

我没有看到提到,这个例子将向你展示 2 位值的 (-) 十进制运算:AB(仅当 A 包含 B 时)

当我们在程序中保存代表位的动词时,需要进行此操作。有时我们需要添加位(如上所示),有时我们需要删除位(如果动词包含则)

111 #decimal 7
-
100 #decimal 4
--------------
011 #decimal 3

使用 python:
7 & ~4 = 3 (从 7 中删除代表 4 的位)

001 #decimal 1
-
100 #decimal 4
--------------
001 #decimal 1

使用 python:
1 & ~4 = 1(从 1 中删除代表 4 的位 - 在这种情况下 1 不“包含”4)..

解决方案 14:

虽然操作整数的位很有用,但通常对于网络协议来说,这些协议可能指定到位,但可能需要操作较长的字节序列(不容易转换为一个整数)。在这种情况下,使用允许对数据进行按位运算的位串库很有用 - 例如,可以将字符串“ABCDEFGHIJKLMNOPQ”导入为字符串或十六进制并对其进行位移位(或执行其他按位运算):

>>> import bitstring
>>> bitstring.BitArray(bytes='ABCDEFGHIJKLMNOPQ') << 4
BitArray('0x142434445464748494a4b4c4d4e4f50510')
>>> bitstring.BitArray(hex='0x4142434445464748494a4b4c4d4e4f5051') << 4
BitArray('0x142434445464748494a4b4c4d4e4f50510')

解决方案 15:

以下按位运算符:&、|、^和~根据其输入返回值,其方式与逻辑门影响信号的方式相同。您可以使用它们来模拟电路。

解决方案 16:

要翻转位(即 1 的补码/反转),您可以执行以下操作:

由于值与全 1 进行异或运算的结果为反转,因此对于给定的位宽,可以使用异或运算来反转它们。

In Binary
a=1010 --> this is 0xA or decimal 10
then 
c = 1111 ^ a = 0101 --> this is 0xF or decimal 15
-----------------
In Python
a=10
b=15
c = a ^ b --> 0101
print(bin(c)) # gives '0b101'

解决方案 17:

您可以使用位掩码将二进制转换为十进制;

int a = 1 << 7;
int c = 55;
for(int i = 0; i < 8; i++){
    System.out.print((a & c) >> 7);     
    c = c << 1;
}

这是 8 位数字,您还可以做更多。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用