Bit Operations
Bit Representation
在C++ int/Java int, 是signed 32-bit,最高位是符号位,所以最大的int是2^31-1=2147483647.
负数的表示是这个数字的正数的二进制表示取反然后+1(complement),这样的好处是在计算机内部不需要cast sign。
原码
反码
补码
0
0000
0000
0000
1
0001
0001
0001
-1
1001
1110
1111
min
max
count
原码
1111(-7)
0111(7)
15
反码
1000(-7)
0111(7)
15
补码
1000(-8)
0111(7)
16

如果只有4位,-8没有原码,所以没办法从补码推回原码。
Integer.MIN_VALUE-1会变成Integer.MAX_VALUE
Integer.MAX_VALUE+1会变成Integer.MIN_VALUE-1
10转2进制
正数:除2取余,直到为0,倒着读
2转10进制
正数:乘2的次幂加起来
ASCII
用一个byte的7位,表示了2^7=128种状态
a map of small numbers to characters
32~126 are printable; others are not printable
0~9, 'A'-'Z', 'a'-'z'都是连续的,所以可以通过这种方式求出它们和0、A或者a的距离
Unicode
超级版ASCII,在ASCII的基础上扩充字符集合,在Java中的char就是Unicode。表示范围是2^16-1 0~65535 前256位是ASCII
在本质上,不管是Unicode还是ASCII都是character set; 在之后再经历character encoding,UTF-8, UTF-16.
Bit Operation
& bitwise AND(&&)
逻辑短路是&&或者AND
&是bitwise operation,所有数和0&都是0,和1&都是自己
| bitwise OR ||
逻辑短路是||或者OR
|是bitwise operation,所有数和1|都是1,和0|都是自己
~ NOT
负数的取反加1的“取反”就是这个~ tilde
-a == (~a)+1 if a>=0
^ XOR
0^0=0; 1^1=0
0^1=1; 1^0=1
交换律 a XOR b = b XOR a
结合律 a XOR (b XOR c) = (a XOR b) XOR c
0是单元 0 XOR a = a
a XOR a =0

<< 左移 右侧补充零
对正数来说,只要不溢出,左移一位相当于*2
>> 右移 算术右移 左侧补充符号位
-1和0不管右移多少位还是原数
-8右移1位可以是-4
-7右移1位也是-4 (所以右移一位不是严格的/2 只是比较接近/2)
左移和右移不改变原来的值
>>> 右移 逻辑右移 左侧补充0, 叫做unsigned right shift
Practical Use Cases
Compression
空间上的压缩:比如 浏览器版本的支持,用一个int表示32个支持或不支持;从右往左,位数依次表示 是否支持当前版本 一个int,4 byte就够
时间上的提升: 用位操作 32个操作变1个操作,32倍的提升
这些提升都是常数倍的 所以不可能是O(nlogn)到O(n)的 但是也挺大的提升了
Building Blocks
Bit tester: Given a number, whether its kth bit is 1
比如,想要知道第k位是否是1,从右到左从0开始数
x&(1<<k)==0 or 8
(x>>k)&1==0 or 1 (preferable)
Bit setter: Set kth bit to 1, and the rest stays the same
x = x | (1 << k) 任何位or0都是自己; or1都是1
Bit setter: Set kth bit to 0, and the rest stays the same
x = x & (~(1<<k) ) 任何位&1都是自己 &0都是0
Problems
Determine whether a number x is a power of 2 (2^n, n>=0)
x>0 必须满足
x的二进制表示只有一个1
要clarify: 是一个整数
如果x是2的幂,and了x-1后一定不会有重叠的1位,所以&之后一定是0 如果x不是2的幂, and了x-1后只会消掉一个1,所以&后一定不可能为0
Determine the # of bits are different between 2 positive integers
xor 然后取多少个1
如何数1: Hamming Weight
What happens if we assign a negative number to an unsigned integer
int: 32, signed; long: 64, signed; short: 16, signed; char: 16, unsigned; byte: 8, unsigned -2^7, 2^7-1 256个
所以下面的Java Code:
Principle 1: 当同位数的整形之间互相转化时,二进制的表示是不变的,变的是后续语句对这个数的理解
Principle 2: extend时,如果原先是有符号数,补充符号位,如果是无符号数,补充0
Principle 3: 长变短时,直接truncate前面多余的位数
Determine whether a string contains unique characters
xor每一个char不对,因为
a-> 65, aa-->0, aaa->65 扎心了
hashset size=26
boolean array, size =26
bitmap
Assume: 只有a-z的字母,那就可以用一个int,32位的前26位来map它们和字母a-z的关系
如果是ASCII,256个,就一定是0~255的这个有序区间里。需要8个integer来表示,比如'b'=98,b%32=2,b/32=3,说明在3bucket里的第二个从右往左2位(都是从0开始)
How to reverse all bits of a number
用2 pointers,reverse string的方法
记得swap后赋值,因为int是primitive type
swap里的操作,交换,如果
XOR 1就是取反
10进制Number to 16进制
其实是0b到0X因为计算机里都是2进制,所以可以每四组一起,8421一个个抠出来;
怎么扣?(>>28)&0xF (>>24)&0xF
实现Integer.parseint这个method
‘1912’ --> ‘1’ ‘9’ ‘1’ ‘2’ -->1 9 1 2 -->1912
反过来 1912-->-->1 9 1 2 ‘1’ ‘9’ ‘1’ ‘2’-->‘1912’ 这里有长到短的强制转化
Convert 'd'-->'D'
它-'a'+'A'
Char to Hex digit
如果在0~9之间,-'0';
如果在'a'~'f'之间,-‘a’+10
如果在'A'~'F'之间,-‘A’+10
Last updated