计算机二进制的一些基础

二进制数

x表示待转换的二进制数,U是unsigned,T是补码(Two's Complement)
w是二进制的位数
n是从右到左的位数,从0开始。x_n是具体位上的值,比如1111。第零位到第四位都是1

b2u_b2t.png

二进制数的扩展和截取

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

    1. 1011(-5) 4位截取成3位,则结果是011 = 3 这是一种类似于mod的操作,(-5+8)mod 8 = 3
    2. 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
​```

你可能感兴趣的:(计算机二进制的一些基础)