数据底层都是二进制组成,如何打印int 和 long类型数字的位信息?
int 类型为基本数据类型,占4字节,32位。long类型也为基本数据类型,占8字节,84位。
这里需要用的 “&” 与运算。
& : 与运算,当两个数字执行此运算,会在底层比较二进制信息,逐个值对比,然后返回计算后新生成的数据。规则为:将二进制的数据进行对比,如果两个数均为1,则生成的新数据的这个位置为1;如果这个位置上两个数据的值 不是都为1则将这个位置赋值为0。
例:
@Test
public void test2() {
int a = 123; //00000000000000000000000001111011
int b = 1340; //00000000000000000000010100111100
//两个位置都是1 才会出1,否则其他都是0
printI(a&b); //通过自定义的方法打印位信息
System.out.println(a&b); //56
//00000000000000000000000000111000
}
结合 "<<" (左移) 位运算,逐个去对比,得到结果,然后打印出来。
1的位信息: 00000000000000000000000000000001 ,让1一位一位的左移 去跟数据进行对比
private void printI(int num) {
for (int i = 31; i >= 0; i--) {
// & 与运算 (0与0,0与1相遇为0)
//因为这个特性,左移位的数字与num与运算,如果不是1,则得到32位0,数值为0
System.out.print((num & (1 << i)) == 0 ? "0" : "1");
}
System.out.println();
}
第一次先将1左移31位,到达最左侧,10000000000000000000000000000000,去与这个num 进行与运算,如果这个位置上不为1,则会返回00000000000000000000000000000000,结果为0,此时打印0,如果不为0,则打印1,就可以得到这个整数的 位信息了。(如果为1,返回的新数肯定不为0)。
打印64位信息也一个原理:
//打印64位信息 用与& 运算实现
private void printL(long num) {
for (int i = 63; i >= 0; i--) {
System.out.print((num & (1L << i)) == 0 ? "0" : "1");
}
System.out.println();
}
@Test
public void testLong() {
long start = System.nanoTime();
long num1 = 1L;
long num2 = 2L;
long num = 123L;
printL(num1);
printL(num2);
printL(num);
long end=System.nanoTime();
System.out.println(end-start);
/*
0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000010
0000000000000000000000000000000000000000000000000000000001111011
*/
}
& 与运算:两个数进行“&”与运算,二进制数据进行对比,如果两数不相同则返回0,两个数都为1则这个位置返回一个1。
| 或运算:两个数进行 “|”或运算,二进制数据进行对比,如果有一个为1,则这个位置返回1。
^ 异或运算:两个数进行“^”异或运算,二进制数据进行对比,如果两个数一致,则这个位置返回0,如果不一致,这个位置返回1
//或 | 异或^
@Test
public void test2() {
int a = 123;
int b = 1340;
printI(a);
printI(b);
System.out.println("===============");
//两个数或运算,只要有一个地方有1,其他都变1
printI(a | b);
//两个位置都是1 才会出1,否则其他都是0
printI(a & b);
//两个位置相同 就为0 不同为1
printI(a ^ b);
/*00000000000000000000000001111011
00000000000000000000010100111100
===============
00000000000000000000010101111111
00000000000000000000000000111000
00000000000000000000010101000111*/
}
位运算:<< 无符号左移(右移才有带符号右移)
//位运算 左移位 及 &与运算,左移位都是无符号,只有右移才是有符号
//数字左移一位,相当于num*2
@Test
public void testLeft() {
//左移位运算 1向左移动31位,剩余的用0补上 比如 1<<31
//1向左移动1位,剩余用0补全 为2
System.out.println(1 << 1);
//左移2位 位4
System.out.println(1 << 2);
System.out.println(1 << 31);
// & 与运算
System.out.println(2 & (1 << 0));
//运算为:2的0次方+2的1次方+2的2次方,1只有一个1,2的0次方
int num = 1;
int num1 = 2345;
printI(num);
printI(num << 1);
printI(num1);
printI(num1 << 1);
}
~ 取反,0变为1,1变为0 ,最左的位置为符号位。
~a+1 = -a 用这种逻辑,方便运算,后续运算都用一套逻辑。
//整型最大值及 正负数如何表示?32位最多能表示40多亿 2的32次方 -1;(因为0要算上,所以最大值要-1)
//0归属在非负区域,负数最小值 绝对值能达到2的31次方,取反最后+1,就把符号位占用了。
//实际上 int 最多是20多亿 2的31次方-1 ,因为有正负,如果无符号数,就可以都用了40多亿 ,所以无符号的最大值比有符号的最大值大
@Test
public void test() {
//正型 真正表示值的范围是 0位到30位的范围,最高位留着既可以表示正,也可以表示负
int max = Integer.MAX_VALUE;
System.out.println(max); //2147483647
printI(max); //01111111111111111111111111111111
//最高位是0 则此数肯定不是负数
int min = Integer.MIN_VALUE;
System.out.println(min); //-2147483648
printI(min); //10000000000000000000000000000000
System.out.println("01111111111111111111111111111111".length());
//int的范围是 -2的31次方~2的31次方-1
//如果是负数,符号位一定是1,符号位以外的数全部取反,末尾+1,则表示值是多少
printI(-1); //11111111111111111111111111111111 符号位以外的,全部取反1变为0...0;末尾+1以后的值 就为具体值;
printI(-2); //11111111111111111111111111111110
printI(-3); //11111111111111111111111111111101 全部取反为10000000000000000000000000000010 +1 ->10000000000000000000000000000011
}
//取反 ;负数的值就是 取反+1
@Test
public void test1() {
int a = 1349811;
//取反操作
int b = -a;
//打印32位数
printI(a); //00000000000101001001100010110011
printI(b); //11111111111010110110011101001101 全部相反,取反后+1则为值
//取反操作+1 ,就是负的
int b1 = (~a + 1);
printI(b1); //11111111111010110110011101001101
//整数最小数取反 及0取反
System.out.println("===最小数取反+1及0取反是自己=====");
int min = Integer.MIN_VALUE;
printI(min);
printI(~min); //取反
//取反+1
printI(~min + 1);
printI(0);
printI(-0);
/*
===最小数取反+1及0取反是自己=====
10000000000000000000000000000000
01111111111111111111111111111111
10000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
*/
}