二进制
负数的十进制转二进制数(-2 -> 1110):
-
正数 - 1,再取反,得到负数的二进制。
-
例如:-2 :0010 -> 0010 - 1 -> 0001 -> 取反 -> 1110
负数的二进制转十进制(1001 -> -7):
- 负数取反,再 + 1,得到正数x,则结果为 -x
- 例如:1001 -> 取反 -> 0110 -> 0110 + 1 -> 0111 ,则 - x = - 7
无符号范围:
0 --- 2^(n-1)
,n为符号位数
有符号范围:
- 正数范围:
0 --- 2^(n-1) - 1
,n为符号位数 - 负数范围:
-2^(n-1) --- -1
,n为符号位数
~
相反数:
- 原数取反之后再加1,就是它的相反数
- 负数的最小值不能转换出它的相反数,
因为转换后还是原来的值,正数范围没有对应的数
位运算:
|
:两个位都为0时,结果才为0,只要符号位有1就保留&
:两个位都为1时,结果才为1^
:两个位相同为0,相异为1穿透性
: 两个位都会执行,会一直穿透下去<< (左移)
:左移一位,整体状态向左移动一位,最低位(右边) 补一个0,左移多少位就补多少个0,非负数<< i
等同于乘以2的i次方,只有非负数符合这个特征,负数不要用
>> (右移)
:右移一位,整体状态向右移动一位,最高位(左边) 补一个1,右移多少位就补多少个1,非负数>> i
等同于除以2的i次方,只有非负数符合这个特征,负数不要用
>>> (右移)
:右移一位,整体状态向右移动一位,最高位(左边) 补一个0,右移多少位就补多少个0
逻辑运算:
||
:两个位都为false时,结果才为false,穿透性
:当有一个为true就停止穿透,后面的不会继续执行&&
:两个位都为true时,结果才为true,穿透性
:当有一个为false就停止穿透,后面的不会继续执行
为什么这么设计二进制:
- 为了加法的逻辑是一套逻辑,没有条件转移,提高运算速度
- 用位运算实现加减乘除,计算机中只有位运算逻辑单元,减乘除都是由加法高效地拼出来的
关于溢出:
- 自己确保自己的调用所得到的结果不会溢出,一定是自己确保的,计算机不会给你做检查
打印二进制:
-
System.out.print((num & (1 << i)) == 0 ? "0" : "1");
-
状态与1位移多少位进行与运算,结果为0则该位状态为0,大于0则为1
-
long类型的数字num,有64位
num & (1 << 48),这种写法不对
因为1是一个int类型,只有32位,所以(1 << 48)早就溢出了,所以无意义
应该写出:num &(1L << 48)