zoukankan      html  css  js  c++  java
  • 深入理解计算机系统--整形、浮点数

    基础

     

    信息在计算机中都是以0、1来表示的,这一点不用赘述。

     

    bit:每一个表示0、1的内存位,叫做bit(位)。

     

    byte:现代计算机大多用8位的内存块作为最小可寻址内存单位,叫做byte(字节)

     

     

    十六进制表示法:

    一般认为,以0X开头的数字常量是十六进制的值。进制对应关系如下:

     

     

    数据寻址/字节顺序

     

    虚拟内存:计算机程序会将内存视为一个非常大的连续的byte数组,这个byte数组就是虚拟内存。

    数组里每一个byte都有一个唯一数字来标识,这个数字就是内存地址。

     

    现实中,很多信息、变量都是大于一个byte的,无法用一个单纯的内存地址来表示。

    因此,首先需要一个内存地址,在加上对应数据类型的偏移量,这样就可以明确这个信息对应的内存区域了。

     

    然后还需要一个规定的存储顺序。最高有效位 -> 最低有效位 这种称为大端法,最低有效位 -> 最高有效位这种称为小端法。

     

    举例:

     

    十进制:2190,二进制:00001000 10001110,16进制:0x088e

    这个如果用大端法表示,那就是 00001000 10001110;

    如果用小端法表示,那就是 10001110 00001000

    目前大多数操作系统都是用小端法表示的(Windows、Android、IOS)

     

    提问:大端法、小端法有什么优缺?为什么会出现两种方式?为什么大多数计算机都采用了小端法?

     

    位运算

    布尔运算

    假设有两个bit,值分别是p和q;

    ~:

    非,NOT。

    1010~ = 0101

     

    &:

    与,AND,p=1且q=1是才为1。

    1010 & 1100 = 1000

     

    |:

    或,OR,p=1或q=1时为真。

    1010 | 1100 = 1110

     

    ^:

    异或,(p=1或q=1) 且 p!=q时为真。

     

    1010 ^ 1100 = 0110;1100 ^ 1100 = 0000;

     

    习题

    1、判断数字奇偶性

    2、一个集合里,有一个数字出现了一次,其他所有数字都出现了两次,求这个出现了一次的数字。

     

     

    移位运算

    位移描述的实际上是数学上的高位/低位的移位运动,不是指实际的内存移动。

     

    例如,左移就是低位往高位移动。大端法是向左移动,小端法是向右移动。

    右移反之。

    左移:<<,移动后右侧补零;

    算数右移:>>,移动后补最高有效位的值;

    逻辑右移 >>>,移动后左侧补0:

     

     

    数1

    数2

    原始值

    0110 0011

    1001 0101

    x << 4

    0011 0000

    0101 0000

    x >>> 4(逻辑右移)

    0000 0110

    0000 1001

    x >> 4 (算术右移)

    0000 0110 

    1111 1001

     

     

     

    左移 等于 乘以2;

    右移等于 除以2;

     

    为什么会有算术右移和逻辑右移?

     

     

     

     

     

    整形表示

    无符号(原码)

     

     

    假设有一个整数数据类型有w位,我们可以将位向量写成,表示整个向量。

    表示向量中的每一位。在这个编码中,每一位都取0或者1。

     

    用一个公式(binary to unsigned,二进制转无符号数,长度为w)来表示:

     

    这个公式就是二进制向无符号整形的转换计算过程。

     

    下面说人话:

    0000 1000 转化为无符号整形的过程:

     

     

    意思就是 0000 1000 这个二进制byte在无符号整形表示法下,实际的值是 8 。

     

    提问:如何表示负数?

     

     

     

     

    有符号(补码)

    顶一个一个函数:

     

    对于向量:

     

     

    说人话:

    0000 1000:

     

     

     

    1110 1000:

     

    1111 1111 = -1;

    1000 0000 = -128

     

     

     

    除了负整数除以2等于其右移1位加1外,所有的整数除以2与右移1位等价。

     

    浮点数

     

    二进制小数

     

    学习浮点数表示有一个前提,就是要明白二进制小数的含义。

     

    一个形如:

     

     

    的表示法,每一位的取值范围是0和1,这种表示法表示的数字b的定义如下:

     

     

    说人话:

     

    1001.0011 =  =

     

    也就是9.1875。

     

    小数点左移一位:100.10011 = 4.59375

     

    小数点右移一位:10010.001 = 18.375

     

    提问:小数点左移右移有什么含义?

     

     

    IEEE浮点数

     

    这个就不详细描述定义了,太复杂了。直接说人话。

     

    大体就是把一个浮点数表示为尾数乘以2的指数次方再添上符号。float和double的规格如下:

     

    符号位     阶码      尾数     长度

    float           1           8         23       32
    double        1          11         52       64

     

    先解释一下这几个部分:

    符号位s表示正负,0是正1是负;

    尾数M表示的含义是一个形如 1.00110.....的二进制小数,整数位都是有且仅有1。因为每个尾数都是整数部分只有1,所以保存时去掉整数位的1,只保留小数点后面的部分。

     

    阶码E表示的是,尾数M 需要乘以 2的E次幂,才能得到实际表示的值。E也不是直接存储的字面值,而是有一些隐含逻辑。

     

    实例讲解:

     

    1、求38414.4D的IEEE二进制表示法

     

    此数是Double,64位,阶码11位,尾数有52位。

     

    符号位s:正数,为0;

    尾数M:38414.4,用二进制表示是:0.4=0.5*0+0.25*1+0.125*1+0.0625*0+……

     

    这个永远也写不完,这时候就只取53位(尾数可以放52位,最前面一位可以省略)

    38414.4(10)=1001011000001110.0110011001100110011001100110011001100(2)

     

    =1.001011000001110 0110011001100110011001100110011001100(2) *

     

    标红部分S就是存到尾数M里的数据;

     

    这时候来算阶码E:

    在算尾数时,后面的2^15就是算阶码的关键。阶码的作用就是把尾数还原成二进制小数。如果想把S转换成实际的二进制小数,则需要1.S * 2^15次方,而E存储的就是这个15次幂这个信息。

     

    Double的阶码有11位,可以保存-1024 ~ 1023这个范围的指数。因为指数是可以为负的,为了方便保存、计算,这里并没有采用补码来保存阶码,而是用移码,也就是实际指数 + 1023。这样做的好处是可以方便的比较浮点数大小,提升效率。11位无符号可以表示0-2047范围的数字。

     

    那么15对应的阶码E就是15+1023 = 1038,二进制:100 00001110;

    那么38414.4D在内存中的存储就是:

    0 10000001110 0010 11000001 110 01100  11001100  11001100  11001100  11001100

     

    问题1:如果表示0?如何表示无穷大?

     

    问题2:阶码移码的表示范围?

     

    用阶码全0 尾数全0表示0,用阶码全1尾数为0表示无穷大;

     

    11为阶码能表述的无符号数范围就只剩下1-2046这个范围了,减去1023,则就对应的实际指数表示范围就是-1022~1023这个范围。

     

     

     

     

    csonezp@gmail.com
  • 相关阅读:
    Android通知栏介绍与适配总结
    Java emoji持久化mysql
    css自适应
    常用网址总结
    前端开发常用技巧
    JAVA问题集锦Ⅰ
    Android之常见问题集锦Ⅱ
    Java集合之ConcurrentHashMap.addCount解析
    Java集合之ConcurrentHashMap解析
    Java数据结构之Map
  • 原文地址:https://www.cnblogs.com/csonezp/p/14927124.html
Copyright © 2011-2022 走看看