1.位运算相关算法

1.位运算

知识扫盲:

0^N = N
N^N=0
满足交换
A^B=B^A
律结合律
(A^B)^C=A^(B^C)
1.判断奇偶数
  //判断奇数偶数
        int num = 2343;
        if ((num & 1) ==1){  //奇数二进制第一位永远是1
            System.out.println("这个数字是奇数");
        }else {
            System.out.println("这个数字是偶数");
        }
**电路问题总结:

对于:& – > 不管怎样,都会执行"&"符号左右两边的程序

对于:&& – > 只有当符号"&&“左边程序为真(true)后,才会执行符号”&&"右边的程序。

下面来说说运算规则:

对于:& – > 只要左右两边有一个为false,则为false;只有全部都为true的时候,结果为true

对于:&& – > 只要符号左边为false,则结果为false;当左边为true,同时右边也为true,则结果为true

2.获取二进制位数是1还是0

将1移动到该位,做&运算,结果为1则该位为1,否则为0;

//获取某二进制数某位置是1还是0
public static void judgepos(int num, int position) {  //
    int i = 1;
    System.out.println(Integer.toString(num, 2));  //将数字转为二进制数
    System.out.println((num>>(position-1)));
    if (((num>>(position-1))&1) == 1){
        System.out.println("该数第"+position+"为1");
    }else {
        System.out.println("该数第"+position+"为0");
    }

}
3.交换两个整数变量的值
 public void channgTwoNummothed1(int num1, int num2){
        //交换两个整数的值
        //方法一
        System.out.println("使用方法一最初输出的结果为:" +num1 + " 和 " + num2);
        int temp;
        temp=num1;
        num1=num2;
        num2=temp;
        System.out.println("使用方法一输出的结果为:" +num1 + " 和 " + num2);
    }

    //方法二
    public void channgTwoNummothed2(int num1, int num2){
        //交换两个整数的值
        //方法二
        System.out.println("使用方法二最初输出的结果为:" +num1 + " 和 " + num2);
        num1 = num1+num2;
        num2 = num1 - num2;
        num1 = num1 = num2;
        System.out.println("使用方法二输出的结果为:" +num1 + " 和 " + num2);
    }
    public void channgTwoNummothed3(int num1, int num2){
        //交换两个整数的值
        //方法三
        System.out.println("使用方法三最初输出的结果为:" +num1 + " 和 " + num2);
        num1 = num1^num2;
        num2 = num1^num2;
        num1 = num1^num2;
        System.out.println("使用方法三输出的结果为:" +num1 + " 和 " + num2);
    }
    public static void main(String[] args) {
        test1 t1 = new test1();
        int a =1;
        int b =3;
        t1.channgTwoNummothed1(a,b); //方法1
        t1.channgTwoNummothed2(a,b);//方法2
        t1.channgTwoNummothed3(a,b);//方法2
    }
4.将整数的奇数偶数位置互换
private static int m(int i){

        //与运算保留
        int ou = i&0xaaaaaaaa;//和1010 1010 1010 1010 1010 1010 1010 1010做与运算 取出偶数位
        int ji = i&0x55555555;//0101 0101 0101 0101 0101 0101 0101 0101 做与运算取出奇数位
        return (ou>>1)^(ji<<1);
    }
5.
//给定一个介于0~1之间的实数,(如0.625),类型位double,打印它的二进制表示(0.101)
//0.5 0.25 0.125
//如果该数字无法精确的用32位以内的二进制表示,则打印error
//小数的二进制表示就是乘以2看整数位置是0或1
private  static  void m1(){
    double num = 0.625;
    StringBuilder sb = new StringBuilder("0.");
    while(num>0){
        //判断整数部分
        double r = num*2;
        if (r>=1){
            sb.append("1");
            num=r-1;
        }else {
            sb.append("0");
            num=r;
        }

        if (sb.length()>34){
            System.out.println("ERROR");
            return;
        }
    }
    System.out.println(sb.toString());
}
6.
//一个数组里除了某个数字之外,其他的数字都出现了两次.
        //程序找出只出现一次的数字
int[] arr = new int[]{1,2,2,3,1};
for (int i = 1; i < arr.length; i++) {
    arr[0]^=arr[i];  //连续使用异或运算  异或可以消去相同的数字
}
System.out.println(arr[0]);
7.输入一个整数,输出该二进制表示中的1的个数
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
System.out.println(Integer.toString(N,2));//输出输入数字的二进制数  //记住这个进制转换方法 Integer.toString(N,2)
int count = 0;
//方法一
//比对每一位
for (int i = 0 ; i < 32; i++){
    if ((N&(1<<i))==(1<<i)){   //1&1 =0
        count++;
    }
}
System.out.println(count);

//方法二
count = 0;
for (int i = 0; i < 32; i++) {
    if(((N>>i)&1)==1){
        count++;
    }
}
System.out.println(count);

//***********************************************************************************************************
//方法三
count = 0;
while(N!=0){
    N=((N-1)&N);
    count++;
}
System.out.println(count);
8、用一条语句判断一个整数是不是2的整数次方
if((((N-1)&N)==0)){ //01111&10000
    System.out.println("该整数为二的整数次方");
}else {
    System.out.println("该整数不是二的整数次方");
}

9. 位操作交换符号
  • 交换符号将正数变成负数,负数变成正数

    int reversal(int a) {
      return ~a + 1;
    }
    

正数取反加1,正好变成其对应的负数(补码表示);负数取反加一,则变为其原码,即正数


10. 位操作求绝对值
  • 整数的绝对值是其本身,负数的绝对值正好可以对其进行取反加一求得,即我们首先判断其符号位(正数右移 31 位得到 0,负数右移 31 位得到 -1,即 0xffffffff),然后根据符号进行相应的操作
int abs(int a) {
  int i = a >> 31;
  return i == 0 ? a : (~a + 1);
}

上面的操作可以进行优化,可以将 i == 0 的条件判断语句去掉。我们都知道符号位 i 只有两种情况,即 i = 0 为正,i = -1 为负。对于任何数与 0 异或都会保持不变,与 -1 即 0xffffffff 进行异或就相当于对此数进行取反,因此可以将上面三目元算符转换为((a^i)-i),即整数时 a 与 0 异或得到本身,再减去 0,负数时与 0xffffffff 异或将 a 进行取反,然后在加上 1,即减去 i(i =-1)

int abs2(int a) {
  int i = a >> 31;
  return ((a^i) - i);
}

11. 位操作进行高低位交换
  • 给定一个 16 位的无符号整数,将其高 8 位与低 8 位进行交换,求出交换后的值,如:
34520的二进制表示:
10000110 11011000

将其高8位与低8位进行交换,得到一个新的二进制数:
11011000 10000110
其十进制为55430

从上面移位操作我们可以知道,只要将无符号数 a>>8 即可得到其高 8 位移到低 8 位,高位补 0;将 a<<8 即可将 低 8 位移到高 8 位,低 8 位补 0,然后将 a>>8 和 a<<8 进行或操作既可求得交换后的结果。

unsigned short a = 34520;
a = (a >> 8) | (a << 8);

8. 位操作统计二进制中 1 的个数

统计二进制1的个数可以分别获取每个二进制位数,然后再统计其1的个数,此方法效率比较低。这里介绍另外一种高效的方法,同样以 34520 为例,我们计算其 a &= (a-1)的结果:

  • 第一次:计算前:1000 0110 1101 1000 计算后:1000 0110 1101 0000
  • 第二次:计算前:1000 0110 1101 0000 计算后:1000 0110 1100 0000
  • 第二次:计算前:1000 0110 1100 0000 计算后:1000 0110 1000 0000 我们发现,没计算一次二进制中就少了一个 1,则我们可以通过下面方法去统计:
count = 0  
while(a){  
  a = a & (a - 1);  
  count++; 
}  
1)的结果:

- 第一次:计算前:1000 0110 1101 1000 计算后:1000 0110 1101 0000
- 第二次:计算前:1000 0110 1101 0000 计算后:1000 0110 1100 0000
- 第二次:计算前:1000 0110 1100 0000 计算后:1000 0110 1000 0000 我们发现,没计算一次二进制中就少了一个 1,则我们可以通过下面方法去统计:

```java
count = 0  
while(a){  
  a = a & (a - 1);  
  count++; 
}  
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
八皇后问题是一个经典的回溯算法问题,但是使用位运算可以使得算法更为高效。具体来说,我们可以使用一个整数变量来表示每一行哪些置已经被占用,然后通过位运算来判断某个置是否可以放置皇后。 具体的算法步骤如下: 1. 定义一个长度为8的数组board,用于存储每一行皇后所在的列号。 2. 定义三个整数变量:col、ld、rd,分别表示列、左对角线、右对角线上已经被占用的置。 3. 从第0行开始,依次遍历每一行。 4. 对于当前行i,遍历该行的每一列j。 5. 判断当前置是否可以放置皇后,即判断col、ld、rd三个变量是否有与当前置冲突的置。 6. 如果当前置可以放置皇后,则将该置的列号存入board数组,并更新col、ld、rd三个变量。 7. 递归处理下一行。 8. 如果已经处理完了第7行,则说明找到了一组解,出结果。 9. 回溯到上一行,尝试其他的列。 10. 如果所有的列都尝试完了,仍然没有找到解,则回溯到上一行。 下面是使用位运算实现八皇后问题的Python代码: ```python def solveNQueens(): def dfs(row, col, ld, rd, path, res): if row == n: res.append(path) return for i in range(n): if not (col & 1 << i or ld & 1 << row + i or rd & 1 << row - i + n - 1): dfs(row + 1, col | 1 << i, ld | 1 << row + i, rd | 1 << row - i + n - 1, path + [i], res) n = 8 res = [] dfs(0, 0, 0, 0, [], res) return res print(solveNQueens()) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值