java位运算应用6,Java位运算的应用

一、判断整数的奇偶性

传统思路:

按照传统的思路,判断一个整数的奇偶性是通过用这个数与2求模,看运算结果是否为0

位运算思路:

Java语言中,所有数字存储在内存中,都要先转换成补码的形式。任何一个偶数用补码表示出来后,它的最后一个二进制位都是0,而奇数补码的最后一个二进制位都是1。所以,我们可以通过判断这个整数的补码的最后一位二进制数是0还是1,来判断这个数是偶数还是奇数。判断的方法就是用这个数与1进行按位与的操作,如果结果为0,那么这个数就是偶数,否则就是奇数。

/**

* 判断整数的奇偶, true表示偶数,false表示奇数

*/

public static boolean judgeParity(int x){

return (x & 1) == 0;

}

二、求绝对值

传统思路:

首先判断一个数a是否>=0,如果a>=0,则返回a本身,否则返回a的相反数

位运算思路:

任何一个整数与0进行异或运算后依然保持不变

任何一个整数与-1进行异或运算后再加上1,得到的结果就是这个数的相反数

数字-1用补码的形式表示出来,恰好是一个32位全为1的二进制串。这个二进制串与任何一个其他二进制串进行按位异或运算,都可以达到”取反”的效果,一个正数按位取反后再加1,得到的就是它相反数

int类型的正数经过带符号右移31位之后,得到的必然是0,而负数经过带符号右移31位得到的是-1。我们就可以通过右移所得到的这个0或者-1,判断出这个数是正数还是负数

/**

* 获取绝对值

* int类型的正数经过带符号右移31位之后,得到的必然是0,而负数经过带符号右移31位得到的是-1。我们就可以通过右移所得到的这个0或者-1,判断出这个数是正数还是负数

* 1.任何一个整数与0进行异或运算后依然保持不变

* 2.任何一个整数与-1进行异或运算后再加上1,得到的结果就是这个数的相反数

*/

public static int abs(int x){

int i = x >> 31;//如果x为整数,则i为0,为负数i为-1

return (x ^ i) - i;

}

三、变量交换两个变量的值

传统思路:

借助中间变量来实现

位运算思路:

abb的运算结果等于a

/**

* 交换变量值

* a^b^b的运算结果等于a

*

* @param a

* @param b

*/

public static void exchange(int a, int b){

a = a ^ b;//g = x ^ y

b = a ^ b;//h = g ^ y = x ^ y ^ y = x 还原了a的值,赋值给b

a = a ^ b;//j = g ^ h = x ^ y ^ x

System.out.println("交换结果:a=" + a + " b=" + b);

}

四、找出数组中只出现一次的元素

传统思路:方式有很多,我们随便写一种

//利用HashSetkey元素不重复的特性

HashSet set = new HashSet();

for (int i : array) {

//如果存在,则删除

if(!set.add(i)){

set.remove(i);

}

}

//最后剩下不重复的元素

System.out.println("=======" + set.toString());

位运算思路:

两个相同的数字进行异或运算,结果为0,而任何一个整数与0进行异或运算,其结果都是这个数本身。另外,任意N个整数进行异或操作,满足交换律。

具体实现如下:

/**

* 位运算放方法 限定数组中只有一个只出现一次的元素

* 思路:两个相同的数字进行异或运算,结果为0,而任何一个整数与0进行异或运算,其结果都是这个数本身。另外,任意N个整数进行异或操作,满足交换律。

* @param array

*/

public static void queryOnceBit(int[] array){

int find = 0;

for(int x: array){

find = find ^ x;

}

System.out.println("只出现一次的元素" + find);

}

/**

* 有整型数组a和b,a数组中所有元素都出现在b数组中,但b数组比a数组多出一个元素

* 思路:两个相同的数字进行异或运算,结果为0,而任何一个整数与0进行异或运算,其结果都是这个数本身。另外,任意N个整数进行异或操作,满足交换律。

*

*/

public static void queryOnceBit(int[] arrayA, int[] arrayB){

// int[] arrayA = {1, 5, 6};

// int[] arrayB = {5, 1, 8, 6};

int find = 0;

for(int i = 0; i < arrayA.length; i++){

find = find ^ arrayA[i] ^ arrayB[i];

//0^1^5^5^1^6^8 = 6^8

}

//6^8^6 = 8

find = find ^ arrayB[arrayB.length - 1];

System.out.println("只出现一次的元素" + find);

}

五、字符串加密

假设有两个整数a和b ,a^b的结果为c。我们可以认为a就是原始数据,a与b进行异或运算所得到的c就是加密后的数据,b在加密过程中扮演着”密钥”的角色。

基础:无论是图片还是文本,在计算机当中都是以二进制数的形式进行存储的。既然是二进制数,那么每8位的二进制数,都可以转换成一个byte类型的数据。而N个8位二进制,就可以转换成一个byte数组。概括成一句话就是:任何形式的信息,在计算机当中都可以用byte数组来存储和表示。

/**

* 原理:a^b^b = a

* @param text

* @param key

*/

public static void encoder(String text, byte key){

byte[] bytes = text.getBytes();

byte[] tranCodes = new byte[bytes.length];//用于保存每个加密后的字节

// byte[] keyBytes = key.getBytes();//密钥

System.out.println("原始字符串为:"+ text);

//加密过程

for (int i = 0; i < bytes.length; i++) {

tranCodes[i] = (byte)(bytes[i] ^ key);// 对每个字节进行加密

}

String encode = new String(tranCodes);//用加密后的字节数组创建字符串

System.out.println("加密后的字符串:"+encode);//输出加密后的字符串

//解密过程

for (int i = 0; i < bytes.length; i++) {

bytes[i] = (byte)(tranCodes[i] ^ key);//对每个字节完成解密

}

String decode = new String(bytes);

System.out.println("解密后的字符串:"+decode);//输出解密后的字符串

}

六、计算一个二进制数当中1的个数

二进制数进行右移1位,然后再左移1位,如果经过两次位移运算,这个二进制数仍然保持不变,那么说明这个二进制数的最低位(也就是最右边那1位)上的数字为0,否则说明最低位为1。

00000101 右移一位 00000010

00000010 左移一位 00000100

操作之后不相等,则说明最后一位是1,相等则为0

无符号右移,左边填0,那么不断的无符号右移,当为00000000时则全部计算完毕

/**

* 计算输入int的二进制1的个数

* @param x

* @return

*/

public static int count1(int x){

int count=0;

while(x!=0) {

if((x>>1)<<1 != x) //对a进行"右移再左移",判断其结果是否等于原来的a

{

++count;

}

x = x>>>1;//完成1次判断,对a进行无符号右移并把运算结果赋值给a自身

}

return count;

}

其他应用遇到了再做更新。

参考:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值