我经常碰到涉及排序/未排序数组的面试问题,他们要求你找到这个数组的某种属性。例如finding the number that appears odd number of times in an array或find the missing number in an unsorted array of size one million。通常,该问题会发布其他约束,例如O(n)运行时复杂性或O(1)空间复杂性。 使用逐位操作可以非常有效地解决这两个问题。当然这些都不是全部,有很多像这样的问题。
对我来说,逐位编程似乎更像是基于黑客或直觉,因为它工作在二进制而不是小数。作为一个没有太多现实生活编程经验的大学生,我很好奇这种类型的问题在实际工作中是否真的很受欢迎,或者只是调查员用来选择最聪明的候选人。 如果它们确实有用,它们在什么样的情况下才真正适用?
答案 0 :(得分:3)
在实际编程中,逐位操作是否常用且有用?
共性或适用性取决于手头的问题。
一些现实生活中的项目确实受益于逐位操作。
一些例子:
您通过直接操作视频内存在屏幕上设置单个像素,其中每个像素的颜色由1或4位表示。因此,在每个字节中,您可以打包8或2个像素,并且需要将它们分开。基本上,您的硬件要求使用逐位操作。
您正在处理某种文件格式(例如GIF)或使用单个位或位组来表示信息的网络协议。您的数据要求使用逐位操作。
您需要计算某种checksum(可能是parity或CRC)或hash value,并且一些最适用的算法通过操作来实现有点。
您正在实施(或使用)arbitrary-precision arithmetic库。
您正在实施FFT,您自然需要reverse bits in an integer或在添加时模拟相反方向的进位传播。算法的性质需要一些按位操作。
您的空间不足,需要使用尽可能少的内存,并将多个位值和位组压缩为整个字节,字,双字和四字。您选择使用按位操作来节省空间。
CPU上的分支/跳转成本很高,您希望通过将代码实现为一系列指令来提高性能,而无需任何分支和按位指令可以提供帮助。这里最简单的例子是选择两个中的最小(或最大)整数值。实现它的最自然的方式是使用某种if
语句,最终涉及比较和分支。您选择使用按位操作来提高速度。
您的CPU支持浮点运算,但计算平方根之类的操作是一个缓慢的操作,而不是simulate it using a few fast and simple integer and floating operations。同样,您可以使用浮点格式的位表示进行操作。
您正在模拟CPU或整个计算机,并且在解码指令时,当访问CPU或硬件寄存器的部分时,您需要操作单个位(或位组),只需模拟像位指令一样OR
,AND
,XOR
,NOT
等。您的问题需要逐步指示。
您正在向网络上的其他人(例如此处)或书籍中解释需要逐位操作的逐位算法或技巧或其他内容。 :)
在过去的20年里,我亲自完成了上述所有工作。但是YMMV。
答案 1 :(得分:0)
根据我的经验,当您的目标是大型数据集的速度和效率时,它非常有用。
我使用位向量来表示非常大的集合,这使得存储非常有效,并且比较和组合等操作非常快。我还发现,由于相同的原因,位矩阵非常有用,例如找到大量大型二进制矩阵的交点。使用二进制掩码指定子集也非常有用,例如Matlab和Python的Numpy / Scipy使用二进制掩码(本质上是二进制矩阵)来从矩阵中选择元素的子集。
答案 2 :(得分:0)
使用按位操作严格取决于您的主要问题。
我曾被要求解决一个问题,找不到
的所有数字组合 对于给定的i,在其中具有重复数字,其形式为N * i。
我突然使用了按位操作并使用更好的
生成所有数字时间,但令我惊讶的是,我被要求重写和编码,不使用Bitwise
运营商,因为人们发现没有可读性,许多人必须使用的代码
进一步说。所以,如果你关注性能,请选择Bitwise。
如果可读性是您的关注,请减少其使用。
如果你想要两者兼得,你需要遵循一种用逐位编写代码的好方式
运营商的方式是可读或可理解的。
答案 3 :(得分:0)
虽然如果你真的不关心它,你可以经常在用户级代码中“避免它”,但它对于内存消耗是一个大问题的情况非常有用。通常需要比特操作,甚至在处理硬件设备或嵌入式编程时也需要比特操作。
I / O寄存器通常具有许多不同的配置选项,可通过各种标志位组合进行寻址。或者对于小型嵌入式设备,其内存相对于现代PC RAM大小受到极大限制,您可能习惯于正常工作。
对于热代码中的一些优化,它也非常方便,您希望使用可以用条件代码表示的某些事物的无分支实现,但需要更快的运行时性能。例如,在一些处理器上使用比较常见解决方案的位攻击,可以非常有效地实现找到给定整数的最接近2的幂。
有一本名为“Hacker's Delight”的伟大着作Henry S. Warren Jr.,它充满了对“现实世界”代码中出现的各种问题非常有用的功能。还有一些类似的在线文档。
另一个例子是20世纪70年代麻省理工学院人工智能实验室的着名文件HAKMEM。