java二进制基础知识

  1. 进制转换
    1. 常用进制
    2. eg:二进制转10进制
    3. 十进制转二进制
    4. 二进制的加减乘除
  2. JAVA位运算
    1. ^(亦或)
    2. &(与)
    3. |(或)
    4. <<(左移)
    5. >>(右移)
    6. ~(取反)
    7. >>>(无符号右移)

进制转换

首先我们先来了解下进制间是如何转换的。

常用进制

  • 二进制 : 0-1 逢二进一
  • 八进制 0-7 逢八进一
  • 十进制 0-9 逢十进一
  • 十六进制 0-9 A-F表示10-15 逢十六进一

eg:二进制转10进制

所有向十进制转换的都可以采用这样的方式进行计算,二进制以二为底 8进制以8为底,16进制以16为底

十进制转二进制

二进制的加减乘除

  • 加法:
  • 减法:
  • 乘法:

  • 除法:

    乘法除法暂未研究,后续会进行补充
    了解了这么多我们开始java的位运算吧。

JAVA位运算

java中,位运算包括 ^(亦或), &(与),|(或) ,<<(左移),>>(右移),<<<(无符号左移),>>>(无符号右移)在继续往下看之前,我们还要了解什么是机器码,由于计算机只能识别0和1, 所有在计算机中用0和1表示正负,这就是符号位(最高位表示),符号位连同数据一起代码化的就是机器码。机器码加绝对值表示的数值就是真值。机器码分有符号数和无符号数,无符号数由所有数值表示。

计算机系统中,数值一律用补码来表示:因为补码可以使符号位和数值位统一处理,同时可以使*减法按照加法来处理。数值编码分为原码,反码,补码,符号位(最高位)均为0正1负。*
原码表示最接近真值 ,规定最高位为符号位 0+ 1- 数值在符号位后面以绝对值给出
补码表示就是将符号位作为数值参与运算,并使所有加减以均以加法代替。负数的补码是原码取反加一,正数补码是它本身。
反码是一种特殊的补码,反码的模比补码最低位小1

  • 原码 -> 补码: 数值位取反加1.
  • 补码 -> 原码: 对该补码的数值位 取反 加1.
  • 补码 的绝对值(称为真值):正数的真值就是本身,负数的真值是各位(包括符号位)取反加1(即变成原码并把符号位取反).

NOTE* 补码”或”运算之后为补码

^(亦或)

public static void main(String[] args) {
		int a=-14;// 0000 1110
		int b=-9;//  0000 1001
/*相同为0,不同为1 */
/*     符号位(0)                       | 符号位(1)             14         取反       加一
*      0000  1110   14                  |      1111 0010    -14 补码 0000 1110->1111 0001->1111 0010
*   ^  0000  1001   9                   |  ^   1111 0111     -9 补码 0000 1001->1111 0110->1111 0111
* ---------------                       | -----------------    补码"异或"运算之后为补码
*      0000  0111 补码->源码 0000  0111  |      0000 0101 补码->源码  0000 0101
*      1*2^2+1*2^1+1*2^0=7              | 1*2^2+1*2^0 =5    结果 5
* */
		System.out.println("a与b:"+String.valueOf(a^b));

	}

&(与)

public static void main(String[] args) {
		int a=-1;//0000 0001 ->1111 1110->1111 1111 负数 补符号位(符号位不变)1  取反加一
		int b=10;//0000 1010 符号位0
/*同1为1,否则为0*/
/*                            |
*      1111 1111  -1          |      1111 0010    -14 补码 0000 1110->1111 0001->1111 0010
*   &  0000 1010  10          |   &  1111 0111     -9 补码 0000 1001->1111 0110->1111 0111
* --------------              | ----------------
*      0000 1010 ->0000 1010  |      1111 0010  ->  1000 1101->1000 1110
*      1*2^3+1*2^1=10         |      1*2^3 +1*2^2+1*2^1= -14
*      最高为是0,不用转化             如果最高位为1 即负数 最高位不变 其他位取反,加一 
*
* */
		System.out.println("a与b:"+String.valueOf(a&b));
	}

|(或)

public static void main(String[] args) {
		int a=14;// 0000 1110
		int b=9;//  0000 1001
/*有1为1,否则为0 */
/*     符号位(0)                  |     符号位(1)                   负数最高位为1 其他位取反加一
*      0000  1110   14             |      1111 0010    -14 补码0000 1110->1111 0001->1111 0010
*   |  0000  1001   9              |  |   0000 1001     9  补码
* ---------------                  | -----------------    
*      0000  1111 ->  0000  1111   |      1111 1011   ->1000 0100 -> 1000 0101 
*                                  |      补码转原码取反加一
*      1*2^3+1*2^2+1*2^1+1*2^0=15  |         1*2^2+1*2^0 =5   符号位为负 结果-5
* */
		System.out.println("a与b:"+String.valueOf(a|b));

	}

<<(左移)

左移位运算符为«,其运算规则是:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。

public static void main(String[] args) {
		int a=-14;// 0000 1110
		int b=11; // 0000 1011
		/*                   |符号位(1)取反 | 加一
		*        0000 1110 ->| 1111 0001 ->  | 1111 0010
		*        << 左移1  (1)舍去  1110 0100    左移后的补码 正数最高位补0,负数最高位补1
		*                          1001 1011    符号位不变 取反
		*                          1001 1100
		*                          -  1*2^2+1*2^3+1*2^4= 4+8+16=28
		*                  符号位为负 结果负28
		*---------------------------------------------------------------------
		*                     0 000 1011
		*        << 左移1     0 000 1011 0 正数补0   正数的补码和原码相同
		*                     + 1*2^4+1*2^2+1*2^1= 22
		*
		* */
		System.out.println("a与b:"+String.valueOf(a<<1));
		System.out.println("a与b:"+String.valueOf(b<<1));

	}

>>(右移)

右位移运算符为»,其运算规则是:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补零。

public static void main(String[] args) {
		int a=-14;// 0000 1110
		int b=11; // 0000 1011
		/*                   |符号位(1)取反 | 加一
		*        0000 1110 ->| 1111 0001 ->  | 1111 0010
		*        >> 右移3  111 1111 0(010)舍去    左移后的补码 正数最高位补0,负数最高位补1
		*                  100 0000 1   符号位不变 取反
		*                  100 0001 0    +1
		*                  -     1*2^1=2
		*                  符号位为负 结果负2
		*                  右移与左移不同会把移出去的舍掉
		*---------------------------------------------------------------------
		*                     0 000 1011
		*        >> 右移3     0 000 0001(011)  正数补0   正数的补码和原码相同
		*                     + 1*2^0= 1
		*
		* */
		System.out.println("a与b:"+String.valueOf(a>>3));
		System.out.println("a与b:"+String.valueOf(b>>3));

	}

~(取反)

取反就是1为0,0为1

public static void main(String[] args) {
		int a=~-14;// 0000 1110
		int b=~11; // 0000 1011
		/*
		*     0000 1110 -->1111 0001-->1111 0010
		*     取反后 ---> 0 000 1101  13
		*----------------------------------------------------------------
		*     0000 1011
		*     取反后 ---> 1 111 0100 (最高位为1)负数 负数都是补码表示,所有要转换为原码
		*     转换后 ---> 1 000 1100 --> -12
		*
		* */
		System.out.println("a与b:"+String.valueOf(a));
		System.out.println("a与b:"+String.valueOf(b));

	}

>>>(无符号右移)


public static void main(String[] args) {
		int a = -14;// 0000 1110->1111 0010
		int b=11; // 0000 1011
		/*
		*无符号右移中正数和负数计算方式不同,对于正数,不会改变成负数,对于负数,将会变成正数。
		* --------------------------------------------------
		* 负数无符号右移
		*   11111111111111111111111111110010
		*   00011111111111111111111111111110(010)舍去
		*      536870910
		* --------------------------------------------------
		* 正数无符号右移
		*  00000000000000000000000000001011
		*     00000000000000000000000000001(011)舍去
		*     1
		* */
		System.out.println("a无符号右移3:"+String.valueOf(a>>>3));
		System.out.println("b无符号右移3:"+String.valueOf(b>>>3));

	}

*NOTE: 遇到&= 、|= 、 ^= 、>>= 、>>>=、 <<= 这样的他们表示把计算后的变量重新赋值给变量,就和a+=1 表示 a=a+1 一样。
*NOTE: 为何无符号位移时有32位呢,请看下表


数据结构 字节 范围
boolean 1 true或false
char 2 从字符型对应的整型数来划分,其表示范围是0~65535
byte 1 -128~127
short 2 -32768~32767
int 4 -2147483648~2147483647 (-2^31 ~ 2^31-1)
long 8 -9223372036854775808 ~ 9223372036854775807
float 4 -3.4E38~3.4E38
double 8 -1.7E308~1.7E308