第二章:计算机中的数据

第二章:计算机中的数据

本章结构
基本概念
数据的表示和运算
硬件电路实现
整数
浮点数
无符号
有符号
基本运算部件

Part 1:基本概念

1、进制及其转换

  1. 二进制->八/十六进制

    请添加图片描述

  2. 二进制<->十进制

    请添加图片描述

2、机器数和真值

  1. 真值

    正常人类使用的十进制数

  2. 机器数

    最高位表示符号位(整数为0,负数为1),剩下的是真值绝对值的二进制数

3、四种码(原码、反码、补码、移码)1

请添加图片描述

原码:Sign Magnitude

反码:Ones’ Complement

补码:Two’s Complement

  1. 为什么需要反码和补码?

    人脑可以一眼看出第一位是符号位,然后进行加减乘除运算,但是对于计算机来说,加减乘除是最基本的运算,加入符号位判断,会使得电路变得复杂,于是有人想到让符号位也参与运算中来

  2. 反码和补码的本质定义

    反码(Ones’ Complement):注意为“ones”,其中文翻译为“1们的补集”。这个名称直观的定义了反码的的计算方式如果有有x>0,则有

    (-x)=[1······1]-[x]

    请添加图片描述

    补码(Two’s Complement):"2的补集"同样直观的定义了补码的计算方法

    请添加图片描述

4、数据的存储和边界对齐

  1. 数据的存储2

    • 大端模式:正常人直观的存储模式
    • 小端模式:正常人讨厌的存储模式(与大端模式相反)

    请添加图片描述

  2. 边界对齐

    C/C++数据类型要求边界对齐,这是由于现代存储器常用低位多体交叉存储结果来实现读取加速

    请添加图片描述

Part 2:数据的表示和运算

1、整数

整数常用四种码表示,详见1.3

  1. 位移运算

    • 算术位移:操作对象为有符号数,位移时符号位不变,当对[-x]进行右移时,要添1而不是0
    • 逻辑位移:操作对象为无符号数,位移添0即可
  2. 加减运算

    • 原码:正常运算

    • 补码:同原码,只不过丢弃溢出位

      [A+B]补码=[A]补码+[B]补码

  3. 乘除运算

    3.1 原码

    • 乘法:直接使用竖式乘法计算即可

      请添加图片描述

    • 除法:直接使用竖式计算即可

      请添加图片描述

    3.2补码

    • 乘法:采用booth算法
    • 除法:加减交替法

2、浮点数:IEEE 7543

  1. 科学计数法

    为了表示一个庞大的数字,使用定点数是一件很不明智的事情(十分浪费空间),所以出现了科学计数法,即将一个数表示为如下的形式
    ( ± ) a . b ∗ 1 0 c (\pm)a.b*10^c (±)a.b10c
    在10进制下,a有9种取值,因为0可以表达到10c次中去,计算机中的float变量采用同样的思想,由于二进制数只有2个取值0,1则对于二进制的科学计数法来说a的取值只能是1,即float变量可以表示为
    ( ± ) 1. b ∗ 2 c (\pm)1.b*2^c (±)1.b2c

    我们只需要存储符号位,b和c即可

  2. float的存储和运算

    2.1 float的存储

    float将4B,也就是32位划分成了3个部分来存储符号,b,c

    • 符号:1 bit(0表示正,1表示负)
    • 指数部分:8 bit(采用移码表示,即真值=无符号数(将这八位视为无符号数)-偏移值(127))
    • 尾数部分:23 bit

    在内存中的顺序为 符号位->指数部分->尾数部分

    2.2 float的运算

    在加减运算是先让两个数的阶码保持一致后,再进行运算

  3. float的范围和精度

    • 范围

      • 指数范围

        float的指数有8位,将其视为无符号数,则其范围是0~255,考虑到其偏移值,范围是[-127, +128],由于其全0和全1有特殊的用途,其真实的范围是[-126, +127]

      • 尾数范围

        尾数部分最大是取全1,即1.11······1(小数点后23个1),结合最大的指数2127可知
        1.11 ⋯ 1 ∗ 2 127 = ( 2 − 2 − 23 ) ∗ 2 127 ≈ 3.4 E 38 1.11\cdots1*2^{127}=(2-2^{-23})*2^{127}\approx3.4E38 1.1112127=(2223)21273.4E38

      所以float的范围大概是[-3.4E38, +3.4E38]

    • 精度

      Float在内存中只占4个字节,即只能表示232个数字,但是,float能表示的范围却远超这个数量级,这是因为float变量表示的数据不是均匀分布的(相比于int变量的每隔1存放一个数据)

  4. float特殊值

    • 尾数全0

      • 指数全0:表示0
      • 指数全1:表示无穷
    • 尾数不全为0

      • 指数全0:将尾数位前默认的1修改为0,以提高表示小数的精度
      • 指数全1:Not a Number(NaN)

Part 3:硬件电路实现

1、基本运算部件

首先观察1位bit相加

Input AInput BCarry(进位)Result
1110
1001
0101
0000

可以发现,进位的输出和与门(AND)相同,结果的输出和异或门(XOR)相同,由此可以构造出1位加法电路

请添加图片描述

有了上一位的进位,变要重新考虑1bit相加

Input AInput B上一位进位本位进位结果
11111
11010
10110
10001
01110
01001
00101
00000

由此可以构造出1位全加器

请添加图片描述

1.1 ALU4

请添加图片描述

Part end:参考文献和一些说明


  1. 这个部分参考知乎上这个问题的回答(醉卧沙场大佬的回答 ):https://www.zhihu.com/question/352057791/answer/876413629 ↩︎

  2. 术语“little endian(小端)”和“big endian(大端)”出自Jonathan Swift的《格列佛游 记》(Gulliver’s Trabels)一书,其中交战的两个派别无法就应该从哪一端(小端还是大端)打开一个半熟的鸡蛋达成一致。一下是Jonathan Swift在1726年关于大小端之争历史的描述:“…下面要告诉你的是,Lilliput和Blefuscu这两大强国在过去36个月里一直在苦战。战争开始是由于以下的原因:我们大家都认为,吃鸡蛋前,原始的方法是打破鸡蛋较大的一端,可是当今皇帝的祖父小时候吃鸡蛋,一次按古法打鸡蛋是碰巧将一个手指弄破了,因此他的父亲,当时的皇帝,就下了一道敕令,命令全体臣民吃鸡蛋时打破鸡蛋较小的一端,违令者重罚。老百姓们对这项命令极为反感。历史告诉我们,由此曾发生过六次叛乱,其中一个皇帝送了命,另一个丢了王位。这些叛乱大多都是由Blefuscu的国王大臣们煽动起来的。叛乱平息后,流亡的人总是逃到那个帝国去寻救避难。据估计,先后几次有11000人情愿受死也不肯去打破鸡蛋较小的一端。关于这一争端,曾出版过几百本大部著作,不过大端派的书一直是受禁的,法律也规定该派的任何人不得做官。”在他那个时代,Swift是在讽刺英国(Lilliput)和法国(Blefuscu)之间的持续的冲突。Danny Cohen,一位网络协议的早期开创者,第一次使用这两个术语来指代字节顺序,后来这个术语被广泛接纳了 ↩︎

  3. 参考资料这篇文章(float的精度和取值范围)https://blog.youkuaiyun.com/albertsh/article/details/92385277 ↩︎

  4. 机器字长是计算机进行一次整数运算所能处理的二进制数的位数,因此所有和整数运算相关的数据通路均与机器字长相同(例如ALU和通用寄存器) ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值