语言实现原码定点乘法除法_深入理解计算机对定点数的表示与处理(基于C语言)...

一直想系统的总结一下计算机关于定点数的存储与表示,能清楚直白的阐述其中的原理。个人认为这是非常重要的内容,可以算是真正的内功心法,基础中的基础,能提升对技术的理解能力。

本文重点解决两个问题:

  1. 为什么计算机对于定点数要用补码表示

  2. 怎样理解反码等于原码保持符号位不变,数据位取反;补码等于反码加一

如果你能解释以上两个问题,请飘过!如果有点儿犹豫,不妨静下心来看看;如果0基础,毋庸置疑,赶紧往下撸呀!

前面会介绍一些铺垫性的概念和表述方式,都是为了对核心内容更好的表达。

位、字节、字

我们知道二进制数就只有0和1,而计算机对信息的存储就是使用二进制数字。通常,存储二值信号的单元叫做位(bit)。单个的位只能表示两种状态,没有太大的作用。但是,如果多个位组合起来,那就能表示非常丰富的含义。一般位的单位使用小写字母b表示,例如,10b表示10个bit

计算机中将8个位组成一组,称作字节(byte),作为最小的可寻址的存储单元。存储器的每个字节都由一个唯一的数字来标识,这个标识称为地址。所有可能地址的集合称为虚拟地址空间。我们常说的32位机器,就是指该计算机的最小可寻址的存储单元为4字节,那么,虚拟地址空间就是[0,2^32 -1],也就是4GB。一般字节的单位使用大写字母B表示,例如,10B表示10个字节。

早些年的计算机大多数是32位,如今很多计算机都是64位的。"32位","64位"还有一个名称叫做字长(word size),字长为4表示32位机器,字长为8表示64位机器。

字节8个位的组合形成的一个单元;便是n个字节的组合形成的一个单元,n的大小一般为4或8,32位机器的字长为4个字节,64位机器的字长为8字节。

位、字节、字之间的大小关系是:word > byte > bit。

由于字大小不同,程序的平台移植性需要考虑。

进制

10进制是我们在日常生活种使用了一千多年的数字表示方法,某种角度来说,10进制也是一种"编码"方式。以10为基数,逢10进1。

2进制和16进制是在计算机的世界里,常用的数字"编码"方式。

f4da10e2ae75c7d4b38c0509c2760e7d.png

从上表可以看出,数字0-15有三种不同的"编码"方式。这里之所以反复强调"编码"这个概念,是为了后面的内容做准备。要表示16个数字,若以10进制为度量,则为0-15;如果16进制为度量,则为0-F;若以2进制为度量,则为0000-1111;三种不同的表示形式,但表达的内容都是相同的。

大小端字节序

大小端问题其实可以看做快递存取问题。从哪儿开始存,怎么存?从哪儿开始取,怎么取?

假设有一个空的快递柜,每一层有4个柜子,按照常识,每个柜子都会有一个编号,假设第一层的4柜子的编号依次为0x100-0x103,现在,我们来玩一个游戏,将4种水果放进柜子里面,按照依次存取方式,保证4种水果的摆放顺序不变。每个水果也有编号,苹果(1号)、香蕉(2号)、草莓(3号)、葡萄(4号)

存之前4种水果的摆放顺序是:苹果(1) 香蕉(2) 草莓(3) 葡萄(4)

方法一(类似 大端)

存入:

0x100     0x101     0x102     0x103

苹果(1)    香蕉(2)    草莓(3)   葡萄(4)

取出(从编号小柜子先取):1 2 3 4

方法二(类似 小端)

存入:

0x100     0x101     0x102     0x103

葡萄(4)    草莓(3)  香蕉(2)     苹果(1)

取出(从编号大柜子先取):1 2 3 4

在计算机中,对于占用多字节的对象,同样也要考虑,这个对象的地址在哪儿,该对象的内容按照什么顺序排列在多字节的space中。

前面举了一个实际生活中的栗子,下面再举一个计算机世界的例子:

对于16进制数0x01234567,该数占4个字节,那么以小端序该数在计算机中怎样存储?以大端序该数在计算机中怎样存储?

大端(big endian):(把数值的高位字节放在内存的低位地址上,把数值的低位字节放在内存的高位地址上)

de93dee42ea7c83bbffb9c041537e916.png

小端(little endian):(把数值的高位字节放在高位地址上,低位字节放在低位地址上)

8a0ba9e56d476979801e4ae71c13acce.png

总之,小端序是数值高位对应地址高位,数值低位对应地址低位;而大端序则数值高位对应地址低位,数值低位对应地址高位。小端序在阅读时,通常是将数值字节按照(与我们书写)相反的顺序显示。

书写字节序列的自然方式是最低位字节在左边,而最高位字节在右边,这正好和通常书写数字时最高有效位在左边,最低有效位在右边的方式相反。

由于字节序的不同,要保证读取和写入的字节序相同,发送和接收的字节序相同。

因此,由于字节序和字大小平台差异性,所以二进制数据的可移植性较文本数据弱,需要两端统一。

位向量

位向量只是一种数学上的表示方式,也是为了后文内容做铺垫。所谓位向量就是固定位宽为w,由0和1组成的串。位向量的运算可以定义成向量的每个对应元素之间的运算。而对应元素之间的运算也就是位运算。

26976733707080172f76586d982dba18.png

移位运算

b717ab82883498ccf0f1a832ad3b12e9.png

整数表示

在c语言中支持多种整型数据类型,不同数据类型所表示的取值范围也各不相同,但是其背后的规律值得我们探索。

32位机器的c的整型数据类型的取值范围:

fd99f8861936dad0cf6254ccfc52570b.png

long long(8字节)是在ISO C99标准引入的,所以在此之前的标准中都是占4个字节。

64位机器的c的整型数据类型的取值范围:

1428d781f9c4df87cb3aceaeced240b4.png

在64位机器中,long数据类型占8字节。

观察上述两个表格的取值范围,发现最小值和最大值的绝对值不对称,负数的绝对值比整数的绝对值大1。这是一个有意思的现象,后文在讲解补码时会解释缘由。

无符号整数编码

1677100886fd25c26f181ab50c2d7ea2.png

补码编码

7cef2740708251979d3f37473623632b.png

如果你觉得上面的公式还不够直观,下面再展示一张表:

6881af0eefab4cff0a7af87a61c5f553.png

行文至此,又产生一个问题,为什么计算机表示整数要使用补码而不是使用其他编码方式,如,原码编码、反码编码呢?

原码编码

5c36121731bc6da427a00d776332b042.png

反码编码

99cf44416021cbd44083a2cb5277aaf8.png

总结

通常定点数(相对于浮点数)就是这三种表示方法:原码、反码、补码。

而我们常使用的口诀:反码等于原码保持符号位不变,数据位取反;补码等于反码加一(现在再来看这句结论是否豁然开朗呢!)。在原码与补码的心算转换过程中,常用反码作为过渡。

前面的内容,从数学层面解释了原码、反码、补码的原理。我相信,以后再看到关于整数的表示、原码、反码、补码相关的结论性描述,就不再迷惑了,彩!

另外,在c语言中,有时候当有符号数特别大或特别小,对于初学者处理不好可能对得不到意料之中的值;那是因为c中存在强制类型转换(显示/隐式),一般出问题是由于隐式强制类型转换导致,因为这种问题程序员不容易发现。针对这种问题,只需要记住一点即可,强制类型转换可能导致数值变化,但位模式不变

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值