二进制数
x表示待转换的二进制数,U是unsigned,T是补码(Two's Complement)
w是二进制的位数
n是从右到左的位数,从0开始。x_n是具体位上的值,比如1111。第零位到第四位都是1
二进制数的扩展和截取
Expand
-
Unsigned
高位补0,比如 1111 4位扩展成8位, 则结果是 0000 1111 结果不变,都是15
-
Two's Complement
高位补1,1011 4位扩展成8位,则结果是1111 1011 结果不变,都是 -5。注意,如果是正数,则不应该由补码表示,应当做Unsigned计算。
Truncate
-
Unsigned
执行mod运算,比如 1111(15) 4位截取成3位,则结果是 111 = 15 mod 8 = 7
-
Two's Complement
- 1011(-5) 4位截取成3位,则结果是011 = 3 这是一种类似于mod的操作,(-5+8)mod 8 = 3
- 1101(-3) 4位截取成3位,则结果是101 = -3 结果没变
二进制的算术运算
加法
-
Unsigned
两个无符号数进行加法运算,如果结果没超出Umax则可以正常表示,如果超出Umax,则对结果执行mod运算
比如 1011(11)+0011(3)= 1110(14)能够正常表示
1011(11)+1001(9)= 10100(20)截取借的位后,结果为4
-
Two's Complement
两个补码进行加法运算,如果结果在Tmin和Tmax间能够则可以正常表示
1110(-2)+1101(-3)= 11011,截取借的位后,结果为-5
如果结果小于Tmin,则是负溢出
1110(-2)+1001(-7)= 10111,截取借的位后,结果为7
如果结果大于Tmax,则是正溢出
0010(2)+0111(7)= 1001(-7),结果为-7
乘法
只考虑乘2^n
-
Unsigned
两个无符号数进行乘法运算,没超出Umax则可以正常表示,如果超出Umax,则对结果执行mod运算
0011(3)*0100(4)= 1100(12) 正常表示
0101(5)*0100(4)= 010100 (20)截取借的位后,结果为4,相当于对结果取模
Two's Complement
两个补码进行乘法运算,如果结果在Tmin和Tmax间能够则可以正常表示
1101(-3)* 0010(2) = 11010(-6),截取后仍是-6
0011(3)*0010(2)=0110(6)正常表示
如果结果小于Tmin,则是负溢出
1011(-5)*0010(2)= 10110(-10),截取借的位后,结果为6
如果结果大于Tmax,则是正溢出
0110(6)*0010(2)= 01100(12),截取借的位后,结果为-4
除法
推算方法和乘法类似,通过右移完成,在java中 >>> 是逻辑右移(负数左边补0),>>是算术右移(负数左边补1)
-x
补码x求-x,不管x是正数还是负数,运算规则是每一位按位取反(包括符号位),再加1
0110(6) =》1010(-6)
1001(-7) =》0111(7)
32位和64位
32位系统地址由32bit组成,因此最大内存限制为2^32, 内存地址有32位的二进制表示。64位系统地址由64bit组成,但是现在不存在2^64大小的内存,所以当代64位计算机,一般只使用47位,所以有的时候看到我们能看到0x7ffffabdd124a
这种格式的地址格式,他只有48位,且第一位为0,因此实际使用的只有47位,32位和64位系统的一个地址对应一个计算机的最小存储单元(一个字节)
IEEE二进制浮点数
V=(-1)^s *M * 2^E, V表示任何实数,M的取值空间为[1,2)。
IEEE依据这个公式提出了一种浮点数的标准|S|Exponent|Fractional|
。将一个浮点数分三段表示S是浮点数的符号位0表示正,1表示负。Exponent表示指数,Fractional表示小数。
有3种浮点数的精度
S | Exponent | Fractional | |
---|---|---|---|
单精度 | 1位 | 8位 | 23位 |
双精度 | 1位 | 11位 | 52位 |
扩展精度 | 1位 | 15位 | 64位 |
扩展精度类型是Intel提出的一种精度类型,不讨论
单精度有32位,双精度有64位
Exponent表示指数,且必须是无符号整型,由于无符号整型无法表示负数,IEEE引入了一个bias解决这个问题bias=2^(k-1)-1,k是Exponent的位数
公式中的E=Exponent-bias,这时指数E就包含的正数和负数了。
以单精度为例,bias=127,Exponent的取值范围为[0,255],则E的取值范围为[-127,128],当Exponent为0000 0000时 E=-127,Exponent为1111 1111时E=128。这两种情况的浮点数不是Normalized,这些特殊值保留用于处理特殊值如正负无穷,NaN等,双精度的和单精度类似
Fractional表示小数部分,默认整数位为1,所以实际上Fractional=M-1,双精度类似
举个例子:
15213.0=11101101101101=1.1101101101101*2^13
所以可以表示位0|10001100|11011011011010000000000
Java中float或double丢失精度问题
java中float是单精度的,double是双精度的,他们的小数部分都只能表示k/2^n , 0```
public class LosePrecision {
public static void main(String[] args) {
double d = 1/5f;
System.out.println(d);
}
}
//result: 0.20000000298023224
```