二进制位运算练习
复习一下二进制中的位运算,写些单元测试练习一下
import java.util.Arrays;
import org.junit.Assert;
import org.junit.Test;
/**
* 位运算测试
*/
public class BitCalc {
/**
* 异或运算 ^ </br>
* 运算规则:相同为0,不同为1
*/
@Test
public void testXor() {
// int long 同理
byte a = "a";
System.out.println("a = " + a);
byte b = "b";
System.out.println("b = " + b);
int c = a ^ b;
System.out.println("c = a ^ b = " + c);
System.out.println("c ^ a = " + (c ^ a));
System.out.println("c ^ b = " + (c ^ b));
Assert.assertTrue((c ^ a) == b);
Assert.assertTrue((c ^ b) == a);
// a与b交换
a ^= b;
b ^= a;
a ^= b;
System.out.println("a = " + a);
System.out.println("b = " + b);
Assert.assertTrue((a ^ b) == c);
int source = -14;
int s = ~source + 1;// 求相反数,原理同求补码:反码+1,等效于(source ^ -1) + 1 和
// ~(source-1)
Assert.assertTrue(s == -source);
int x = a;
x = a ^ b ^ x;
}
/**
* 与运算 & </br>
* 运算规则:都为1时为1,其他为0
*/
@Test
public void testAnd() {
byte a = 1 & 1;
Assert.assertTrue(a == 1);
int count = 100000;
Assert.assertTrue((count & 1) == (count % 2));
// 取模运算转化成位运算 (在不产生溢出的情况下) a % (2^n) 等价于 a & (2^n - 1)
for (int i = 1; i < count; i++) {
for (int j = 2; j < 10; j++) {
if (i % (2 << j) == 0) {
Assert.assertTrue((i & ((2 << j) - 1)) == 0);
}
if ((i & ((2 << j) - 1)) == 0) {
Assert.assertTrue((i % (2 << j) == 0));
}
}
}
}
/**
* 右移运算 >> </br>
* 运算规则:将二进制字节右移n位,高位补符号位,低位丢弃
*/
@Test
public void testShiftRight() {
int a = 8 >> 3;
Assert.assertTrue(a == 8 / (2 * 2 * 2));
// (byte) 256=0
System.out.println((byte) 256);
// =》-1
System.out.println((byte) (-5 >> 8 & 0xFF));
// int转byte
int sum = -128;
System.out.println(Integer.toBinaryString(sum));
// int点4个字节
byte[] intByte = new byte[4];
for (int i = 0; i < 4; i++) {
int n = (3 - i) * 8;
// & 0xFF取低8位,好像不需要& 0xFF,强制转换成byte,只取了后8位,前24位丢弃了
intByte[i] = (byte) (sum >> n & 0xFF);
}
System.out.println(Arrays.toString(intByte));
System.out.println(abs(-5));
}
/**
* 计算绝对值
*/
private static int abs(int x) {
int y;
y = x >> 31;
return (x + y) ^ y; // 补码转原码算法
}
/**
* 左移运算 << </br>
* 运算规则:将二进制字节左移n位,低位补0,高位丢弃
*/
@Test
public void testShiftLeft() {
int a = 8 << 3;
Assert.assertTrue(a == 8 * (2 * 2 * 2));
// byte转int
// 11111111 11111111 11111111 11111111=-1
byte[] intByte = new byte[] { -1, -1, -1, -1 };
// =》11111111 00000000=-256
System.out.println(intByte[0] << 8);
// =》00000000 00000000 11111111 00000000=65280
System.out.println(intByte[0] & 0xFF << 8);
int sum = 0;
for (int i = 0; i < 4; i++) {
int n = (3 - i) * 8;
// & 0xFF补零扩充到32位
sum += intByte[i] & 0xFF << n;
}
System.out.println(sum);
System.out.println(Integer.toBinaryString(sum));
// new byte[] { 1, 2, 3, 4 }
System.out.println(Integer.valueOf("00000001000000100000001100000100", 2));
}
/**
* 求平均数 </br>
* @see
* x|y = x&y + x^y </br>
* </br>
* x|y原理:可以理解成同时为1的部分(x&y),加上不同时不1的部分(x^y)</br>
* </br>
* x+y = 2(x&y) + x^y </br>
* x+y = x|y + x&y </br>
* </br>
* x+y原理:把x和y分别拆开成两部分,将4个部分相加</br>
* 第一部分为x和y的二进制码中同时为1的部分(也就是x&y),</br>
* 第二部分为剩下的一个是1,一个是0,或是两个都是0(也就是x|y)</br>
*
*/
@Test
public void average() {
int x = Integer.MAX_VALUE;
int y = Integer.MAX_VALUE - 1;
// int z = (x + y) / 2; =-2,溢出
System.out.println(((x & 1) + (y & 1)) / 2);
System.out.println(x / 2 + y / 2 + ((x & 1) + (y & 1)) / 2);
int z = (x & y) + ((x ^ y) >> 1);
System.out.println(z);
z = (x >> 1) + (y >> 1) + (((x & 1) + (y & 1)) >> 1);
System.out.println(z);
}
/**
* 位操作进行二进制逆序 </br>
* 数34520的二进制表示: 10000110 11011000</br>
* 逆序后则为: 00011011 01100001 它的十进制为7009
*/
@Test
public void oppsiteOrder() {
short a = (short) 34520;
System.out.println(Integer.toBinaryString(a & 0xFFFF));
//前8位与后8位对换
a = (short) ((a >> 8 & 0x00FF | a << 8 & 0xFF00));
System.out.println(Integer.toBinaryString(a & 0xFFFF));
//前后8位中的4位相互对换
a = (short) ((a >> 4 & 0x0F0F | a << 4 & 0xF0F0));
System.out.println(Integer.toBinaryString(a & 0xFFFF));
//每相邻2位相互对换
a = (short) ((a >> 2 & 0x3333 | a << 2 & 0xCCCC));
System.out.println(Integer.toBinaryString(a & 0xFFFF));
//每相邻1位相互对换
a = (short) ((a >> 1 & 0x5555 | a << 1 & 0xAAAA));
System.out.println(Integer.toBinaryString(a & 0xFFFF));
String str = "123456789";
byte[] strBytes = str.getBytes();
for (int i = 0, len = strBytes.length; i < len / 2; i++) {
strBytes[i] ^= strBytes[len - i - 1];
strBytes[len - i - 1] ^= strBytes[i];
strBytes[i] ^= strBytes[len - i - 1];
}
// 987654321,不适合包含中文的字符串
System.out.println(new String(strBytes));
}
}
参考:
https://www.zhihu.com/question/38206659
https://blog.csdn.net/black_OX/article/details/46411997
以上是 二进制位运算练习 的全部内容, 来源链接: utcz.com/z/518172.html