如何设置、清除和切换一点?
当前回答
该程序基于@Jeremy的上述解决方案。如果有人想快速玩耍。
public class BitwiseOperations {
public static void main(String args[]) {
setABit(0, 4); // set the 4th bit, 0000 -> 1000 [8]
clearABit(16, 5); // clear the 5th bit, 10000 -> 00000 [0]
toggleABit(8, 4); // toggle the 4th bit, 1000 -> 0000 [0]
checkABit(8,4); // check the 4th bit 1000 -> true
}
public static void setABit(int input, int n) {
input = input | ( 1 << n-1);
System.out.println(input);
}
public static void clearABit(int input, int n) {
input = input & ~(1 << n-1);
System.out.println(input);
}
public static void toggleABit(int input, int n) {
input = input ^ (1 << n-1);
System.out.println(input);
}
public static void checkABit(int input, int n) {
boolean isSet = ((input >> n-1) & 1) == 1;
System.out.println(isSet);
}
}
Output :
8
0
0
true
其他回答
设置一位
使用按位OR运算符(|)设置位。
number |= 1UL << n;
这将设置数字的第n位。如果要将第1位设置为n-1,那么n应该为零,如果要设置第n位。
如果数字大于无符号长,则使用1ULL;1UL<<n的提升直到评估1UL<<n之后才发生,其中移动超过长的宽度是未定义的行为。这同样适用于所有其他示例。
清除一点
使用位AND运算符(&)清除位。
number &= ~(1UL << n);
这将清除数字的第n位。必须使用按位NOT运算符(~)反转位字符串,然后对其进行AND运算。
稍微扭动一下
XOR运算符(^)可用于切换位。
number ^= 1UL << n;
这将切换数字的第n位。
检查一点
你没有要求这样做,但我不妨补充一下。
要检查一位,请向右移动数字n,然后按位“与”:
bit = (number >> n) & 1U;
这将把数字第n位的值放入变量位。
将第n位更改为x
在2的补码C++实现中,可以通过以下方式将第n位设置为1或0:
number ^= (-x ^ number) & (1UL << n);
如果x为1,则设置位n,如果x为0,则清除位n。如果x有其他值,则会得到垃圾。x=!!x将其布尔化为0或1。
要使其独立于2的补码否定行为(其中-1设置了所有位,与1的补码或符号/大小C++实现不同),请使用无符号否定。
number ^= (-(unsigned long)x ^ number) & (1UL << n);
or
unsigned long newbit = !!x; // Also booleanize to force 0 or 1
number ^= (-newbit ^ number) & (1UL << n);
使用无符号类型进行可移植位操作通常是一个好主意。
or
number = (number & ~(1UL << n)) | (x << n);
(number&~(1UL<<n))将清除第n位,(x<<n)将第n位设置为x。
一般来说,不复制/粘贴代码也是一个好主意,因为很多人使用预处理器宏(如社区wiki答案)或某种封装。
使用标准C++库:std::bitset<N>。
或者Boost版本:Boost::dynamic_bitset。
没有必要自己动手:
#include <bitset>
#include <iostream>
int main()
{
std::bitset<5> x;
x[1] = 1;
x[2] = 0;
// Note x[0-4] valid
std::cout << x << std::endl;
}
[Alpha:] > ./a.out
00010
与标准库编译时大小的位集相比,Boost版本允许运行时大小的比特集。
另一个选项是使用位字段:
struct bits {
unsigned int a:1;
unsigned int b:1;
unsigned int c:1;
};
struct bits mybits;
定义了一个3位字段(实际上是三个1位字段)。比特操作现在变得简单了一点(哈哈):
设置或清除一位:
mybits.b = 1;
mybits.c = 0;
要切换一位,请执行以下操作:
mybits.a = !mybits.a;
mybits.b = ~mybits.b;
mybits.c ^= 1; /* all work */
检查一点:
if (mybits.c) //if mybits.c is non zero the next line below will execute
这仅适用于固定大小的位字段。否则,您必须求助于前面文章中描述的比特旋转技术。
如何设置、清除和切换单个位?
要解决试图形成掩码时的常见编码陷阱,请执行以下操作:1并不总是足够宽
当数字的类型大于1时会出现什么问题?x对于移位1<<x可能太大,导致未定义的行为(UB)。即使x不太大,~也可能无法翻转足够多的最高有效位。
// assume 32 bit int/unsigned
unsigned long long number = foo();
unsigned x = 40;
number |= (1 << x); // UB
number ^= (1 << x); // UB
number &= ~(1 << x); // UB
x = 10;
number &= ~(1 << x); // Wrong mask, not wide enough
要确保1足够宽:
代码可以使用1ull或pedatically(uintmax_t)1并让编译器进行优化。
number |= (1ull << x);
number |= ((uintmax_t)1 << x);
或铸造-这使得编码/审查/维护问题保持铸造正确和最新。
number |= (type_of_number)1 << x;
或者通过强制一个至少与数字类型一样宽的数学运算来温和地推广1。
number |= (number*0 + 1) << x;
与大多数位操作一样,最好使用无符号类型而不是有符号类型
该程序基于@Jeremy的上述解决方案。如果有人想快速玩耍。
public class BitwiseOperations {
public static void main(String args[]) {
setABit(0, 4); // set the 4th bit, 0000 -> 1000 [8]
clearABit(16, 5); // clear the 5th bit, 10000 -> 00000 [0]
toggleABit(8, 4); // toggle the 4th bit, 1000 -> 0000 [0]
checkABit(8,4); // check the 4th bit 1000 -> true
}
public static void setABit(int input, int n) {
input = input | ( 1 << n-1);
System.out.println(input);
}
public static void clearABit(int input, int n) {
input = input & ~(1 << n-1);
System.out.println(input);
}
public static void toggleABit(int input, int n) {
input = input ^ (1 << n-1);
System.out.println(input);
}
public static void checkABit(int input, int n) {
boolean isSet = ((input >> n-1) & 1) == 1;
System.out.println(isSet);
}
}
Output :
8
0
0
true