(1)更新i位:
1)setBit与clearBit的结合。
2)实现:
/*
目的:将num的第i位,更新为v表示的数,
V的取值为0或者1.
步骤:先将num的第i位清0.然后将v左移i位,最后二者相或。
*/
int updataBit(int num ,int i ,int v){
int mask=~(1<<i);
return (num & mask)|(v<<i);
}
--------
(2)判断偶数:
用 n&1==0 来代替 n%2==0来判断偶数。
(偶数只需要该数的二进制形式的最低一位为0.)
-------
(3)判断n是否为2的某次方:
n&(n-1)==0为真,则n为2的某次方。
分析:
二进制形式:如
1101011000
- 1
=1101010111
十进制形式:如:
593100
- 1
=593099
分析:将一个数减去1,需要将该数做如下变化:从右往左,直至第一个1出现,将该位1变成0,该位右边的其他位变成1.
综上:n与n-1的区别为:n的二进制形式中(从右往左设第一个1出现的位置是在i位)。
则n与n-1的区别为:0位到i位,n与n-1完全相反;i+1位到最高位,n与n-1相同。
所以:n&(n-1)==0,则只有i+1位到最高位为0,所以n中只有一个1.即为2的某次方。
---------
(4)给定一个32位的整数M,N、编写方法,从N的第j位开始,到第i位用M来替换。
如:N=10000000000,M=10011,i=2,j=6,则N=10001001100
1)思路:
1.将N的i位到j位清零。
2.对M执行移位操作,使得j与i之间的位对齐。
3.M或上N.
2)代码实现:
/*
掩码的获取:如i=2,j=4,掩码为mask=11100011;
left=11100000,right=00000011;
mask=left|right;
*/
int updateBits(int n,int m ,int i,int j){
//将N的i到j位清零,需要设置一个i到j位为0,其他位为1的掩码。
//可以先创建左半部分,然后创建右半部分,最终得到整个掩码。
int allOnes=~0;//一连串的1
int left=allOnes<<(j+1);
int right=(1<<i )-1;
int mask=right|left;
int n_clear=n&mask;//将n的i到j位清零。
int m_shift=m<<i;//将m移位。
return n_clear|m_shift;
}
-------
(5)打印一个0到1之间的小数的二进制形式;
如:十进制小数0.625(10)的二进制形式为0.101(2)
因为0.101(2)=1*(2^-1)+0*(2^-2)+1*(2^-3)=0.625(10).
1)思路:
可以将n不断的乘以2,看2n是否大于1来判断原n的小数点后面是1还是0.
如:0.101(2)*2=1.01,可以分离出来1.
2)实现:
public static String printBinary(double num){
if(num>=1 || num<=0)
return "error";
StringBuilder binary=new StringBuilder();
binary.append(".");//添加小数点
while(num>0){
if(binary.length()>=32)
return "error";
double r=num*2;
if(r>=1){
binary.append("1");
num=r-1;
}else{
binary.append("0");
num=r;
}
}//循环结束时num=0;
return binary.toString();
}
-------
(6)编写一个函数,确定需要改变几位,才可以将A改变成B?
1)分析:
需要找出两个数之间的不同位,只需要异或即可。只需要计算一下A^B中有几位为1即可。
2)实现:
int bitSwapRequired(int a,int b){
int count=0;
for(int c=a^b;c!=0;c=c>>1){
count+=(c&1);//c&1即取c的最低位。
}
return count;
}
改进:
上面的做法是不断取得c的最低位,其实可以不断地翻转最低有效位,计算要多少次C才可以翻转为0.操作C=C&(C-1);会清除掉C的最低有效位。
最低有效位(即从右往左,第一个1出现的位置)
int bitSwapRequired(int a,int b){
int count=0;
for(c=a^b;c!=0;c=c&(c-1)){
count++;
}
return count;
}
--------
(7)交换某个整数的奇数位与偶数位。
如:位0与位1交换,位2与位3交换。
1)分析:
可以先操作奇数位,然后操作偶数位;
1.将数字n的奇数位右移1位。
2.将数字n的偶数位左移1位。
3,合并两次结果。
可以使用10101010(即0xAA)作为掩码,提取奇数位,然后右移一位。
可以使用01010101(即Ox55)作为掩码,提取偶数位,然后左移一位。
int swapOddEvenBits(int n){
int even=n&(0xaaaaaaaa);
int odd=n&(0x55555555);
return (even>>1)|(odd<<1);
}
注意:此中整数是32位的,如果是64位的整数,则掩码需要改变。
------
(8)给定一列0到n的整数,其中只是缺少一个数字,把这个数字找出来。
方法:将这一列数字相加,然后与0到n的总和比较。两者差值就是缺少的数。
2)变形:
------
(9)给定一个正整数,找出二进制形式中1的个数相同,且大小最接近的那两个数(一个略大,一个略小)。
1)方法一:蛮力法:
在n的二进制表示中,计算出1的个数,然后增加或者减少,直到找到1的个数相同的数字。
2)位操作法:
见下图:
-----
(10)确定一个字符串的所有字符是否全都不同。(即一个字符串中是否没有重复的字符)
(1)方法一:数组。
public boolean isUniqueChars(String str){
if(str.length()>256) return fasle;
boolean[] char_set=new boolean[256];
for(int i=0;i<str.length();i++){
int val=str.charAt(i);
if(char_set[val])
return false;
char_set[val]=ture;
}
return true;
}
(2)方法二:位操作。
public boolean isUniqueChars(String str){
if(str.length()>256) return false;
int checker=0;
for(int i=0;i<str.length();i++){
int val=str.charAt[i]-'a';//假设str中的字符都是小写,且为字母;
if(checker &(1<<val)!=0){//取checker的第val位。
return fasle;
}
checker|=(1<<val);//checker的val位置1.
}
return true;
}
本文介绍了多种位操作技巧,包括更新指定位、判断特定条件、替换区间内的位、打印小数的二进制形式等,并提供了详细的代码实现。
1026

被折叠的 条评论
为什么被折叠?



