一、码制

二进制数正负数三种表示法 —— 原码;反码;补码。
注意:二进制数的第一位是符号位,0正 1负;后面是数值位。

正数的原码 = 反码 = 补码,即符号位为0,位于首位,随后是二进制数绝对值数值
例如10的原码为=0000 1010 ;反码=0000 1010;补码=0000 1010;

负数而言,三种表示方法不一样。
原码:符号位“1”+二进制数绝对值数值
反码:符号位“1”+数值位按位取反
补码:反码+“1” (末位)

重:已知一个数的补码求原码,其实就是对该补码再求补码,因为原码和补码互为补数。

二进制反码和补码运算性质:
[[X]反]反=[X]原
[[X]补]补=[X]原
[X]反+[Y]反=[X+Y]反(循环进位)
[X]补+[Y]补=[X+Y]补(舍弃进位)

二、基础运算

1、加法运算
 (4 + 7 = 11)
  0 0 0 0 0 1 0 0   4
+ 0 0 0 0 0 1 1 1   7
------------------
  0 0 0 0 1 0 1 1   11
2、减法运算

需要先把负数转为补码,再相加,例如2+(-10) = -8

       原码        反码        补码
+1   00000010    00000010    00000010
-1   10001010    11110101    11110110
 
  0 0 0 0 0 0 1 0
+ 1 1 1 1 0 1 1 0
------------------
  1 1 1 1 1 0 0 0   -->结果为-8的补码
再多举几个加减的例子
1、10+(-2)= 8
10 原码 = 0000 1010
(-2) 原码:  1000 0010
(-2) 反码:1111 1101
(-2) 补码:1111   1110

  00001010
+ 11111110
------------------
00001000 = 8

2、5 + (-11) = -6
5 原码 = 0000 0101
(-11) 原码:  1000 1011
(-11) 反码:1111 0100
(-11) 补码:1111 0101

   0000 0101
+ 1111 0101
------------------
1111 1010  	 -6的补码
验证一下原码
再取(1111 1010)的补码 = 原码 1000 0110 = -6的原码
3、乘法运算

当其中一个乘数是2^n时,等于将另一个乘数的所有二进制位向左移动n位。
而当两个乘数都不是2n时,这时候编译器会将其中一个乘数分解成多个2n相加的结果,然后进行分别运算。

  (0000 1100)  12 x (0000 1000)  8
  相当于:
  8(2^3)+4(2^2)
  (8 << 3) + (8 << 2) = 0110 0000 = 96
4、除法运算

当除数是2^n时,等于将被除数的所有二进制位向右移动n位。
当除数不是2^n时,这个原理比较难并且精度问题。
浮点数简要介绍
由于浮点数的小数位的二进制数据依旧保持2^n的特性,假如10111001属于小数位,那么这部分小数位的值等于:1/2 + 1/4 + 1/8 + 1/16 + 1/128 = 0.9453125。
因此,把一个小数位很多的浮点数(3.14159269453125)存入计算机的时候,所有小数位会被拆解成很多的2^n进行保存。由于位数总是有限的,因此当分解到第n位数溢出时,就会出现精度偏差。另一方面,过多的分解计算势必要消耗大量的时钟周期,这也是大量的浮点数运算容易引发卡顿的原因,比如cell滑动时动态算高。(此处原理未来再具体分析)。#future

5、位运算符

(1)&(按位与):对应两个二进制位均为1时,结果才为1,否则为0。
(2)|(按位或):对应两个二进制位只要有一个为1时,结果就为1,否则为0。
(3)^(按位异或):对应两个二进制位都不相同时,结果才为1,否则为0。(不同为1,相同为0)
(4)~(取反):所有二进制位都变为相反的(0变1,1变0),符号位也变。
(5)>>(右移):右移n位本质是a=a/2^n。把整数a的所有二进制位全部右移n位,符号位不变。(正数)符号位为0时,数值最高位补0。(负数)符号位为1时,数值最高位补0或1,则取决与编译系统,一般最高位补符号位。
(6)<<(左移):左移n位本质是a=a*2^n。把整数a的所有二进制位全部左移n位,溢出的最高位丢弃,包括符号位,低位补0。因此左移会改变正负性。