您的位置:首页 > 理论基础

计算机底层到底是如何存储数字的?

2019-10-12 13:48 1971 查看

计算机对外信息展示方式有文字、图片、音频、视频等,但不论应用在什么地方,信息在机器内部的形式都是一致的,即均为0和1组成的各种编码。

一、有符号数和无符号数

在计算机中参与运算的数有两大类:无符号数和有符号数。

无符号数

计算机中的数均放在寄存器中,通常称寄存器的位数为机器字长。

所谓无符号数,即没有符号的数,在寄存器中的每一位均可用来存放数值。当存放有符号数时,则需留出位置存放符号。

因此,在机器字长相同时,无符号数与有符号数所对应的数值范围是不同的。

以机器字长为16位为例,无符号数的表示范围为 0~65535,而有符号数的表示范围为 -32768 ~ +32767(此数值对应补码表示)。

有符号数

对有符号数而言,符号的“正”、“负”机器是无法识别的,但由于“正”、“负”恰好是两种截然不同的状态,如果用“0“表示“正”,用“1”表示“负”,这样符号也被数字化了,并且规定将它放在有效数字的前面,即组成了有符号数。
例如,+1100 在机器中表示为 01100 ,-1100 在机器中表示为 1 1100 。

在Java语言中,如 int、float 等都是有符号数,故下文所讲都是在有符号数的范畴。

二、机器数与真值

把符号(如+、-)“数字化”的数称为机器数,而把带“+”或“-”符号的数称为真值

一旦符号数字化后,符号和数值就形成了一种新的编码。在运算过程中,符号位能否和数值部分一起参加运算?如果参加运算,符号位又需作哪些处理?这些问题都与符号位和数值位所构成的编码有关,这些编码就是原码、补码、反码和移码。

原码

原码是机器数中最简单的一种表示形式,符号位为0的表示正数,符号位为1的表示负数,数值位即真值的绝对值,故原码表示又称为带符号的绝对值表示。

反码

正数的反码依旧等于原码,负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。

补码

正数的补码码依旧等于原码,负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1。 (即在反码的基础上+1)

移码

同一个真值的移码和补码仅差一个符号位,若将补码的符号位由“0”改为“1”,或从“1”改为“0”,即可得该真值的移码。简单说,无论正负数,只要将其补码的符号位取反即可。

三、定点数与浮点数

在计算机中,小数点不用专门的器件表示,而是按约定的方式标出,共有两种方法表示小数点的存在,即定点表示和浮点表示。定点表示的数称为定点数如 java 语言中的 int),浮点表示的数称为浮点数如 java 语言中的 float、double)。

定点数

小数点固定在某一位置的数为定点数,有以下两种格式。


当小数点位于数符和第一数值位之间时,机器内的数为纯小数;当小数点位于数值位之后时,机器内的数为纯整数

采用定点数的机器称为定点机。数值部分的位数n决定了定点机中数的表示范围。若机器数采用原码,小数定点机中数的表示范围是 -(1 - 2^-n) ~ (1 - 2^-n),整数定点机中数的表示范围是 -(2^n-1) ~ (2^n-1)。

浮点数

实际上计算机中处理的数不一定是纯小数或纯整数(如圆周率3.1416),而且有些数据的数值范围相差很大(如电子的质量9×10-6g,太阳的质量2×103g),它们都不能直接用定点小数或定点整数表示,但均可用浮点数表示。浮点数即小数点的位置可以浮动的数,如

352.47 = 3.5247 * 10^2 = 3524.7 * 10^-1

显然,这里小数点的位置是变化的,但因为分别乘上了不同的 10 的方幂,故值不变。

通常,浮点数被表示成 N = S * r^j , 式中,S为尾数(可正可负),j为阶码(可正可负),r是基数(或基值)。在计算机中,基数可取2,4、8或16等。

浮点数的规格化形式为 N = 0.110101 * 2^10。

浮点数在机器中的形式如下所示。

浮点数由阶码j和尾数S两部分组成。阶符表示阶码数值部分的正负,数符表示尾数数值部分的正负。阶码j反映了浮点数的表示范围及小数点的实际位置。尾数是小数,其位数n反映了浮点数的精度。

定点数与浮点数的比较

定点数和浮点数可从如下几个方面进行比较。

①当浮点机和定点机中数的位数相同时,浮点数的表示范围比定点数的大得多。

②当浮点数为规格化数时,其相对精度远比定点数高。

③浮点数运算要分阶码部分和尾数部分,而且运算结果都要求规格化,故浮点运算步骤比定点运算步骤多,运算速度比定点运算的低,运算线路比定点运算的复杂。

④在溢出的判断方法上,浮点数是对规格化数的阶码进行判断,而定点数是对数值本身进行判断。例如小数定点机中的数其绝对值必须小于1,否则“溢出”,此时要求机器停止运算,进行处理。为了防止溢出,上机前必须选择比例因子,这个工作比较麻烦给编程带来不便。而浮点数的表示范围远比定点数大,仅当“上溢”时机器才停止运算,故一般不必考虑比例因子的选择。

总之,浮点数在数的表示范围、数的精度、溢出处理和程序编程方面(不取比例因子)均优于定点数。但在运算规则、运算速度及硬件成本方面又不如定点数。因此,究竟选用定点数还是浮点数,应根据具体应用综合考虑。一般来说,通用的大型计算机大多采用浮点数,或同时采用定、浮点数;小型、微型及某些专用机、控制机则大多采用定点数。当需要作浮点运算时,可通过软件实现,也可外加浮点扩展硬件(如协处理器)来实现。

四、IEEE 754标准

现代计算机中,浮点数一般采用 IEEE 制定的国际标准,这种标准形式如下:

按 IEEE 标准,常用的浮点数有三种:

符号位S 阶码 尾数 总位数
短实数 1 8 23 32
长实数 1 11 52 64
临时实数 1 15 64 80

其中,S为数符,表示浮点数的正负,但与其有效位(尾数)是分开的。

阶码的真值都被加上一个常数(偏移量),如短实数、长实数和临时实数的偏移量用十进制数表示分别为 127、1023 和 16383。

尾数部分通常都是规格化表示,即写成 1.xxxxxx 的形式,其中 xxxxxx 表示小数部分。IEEE 754规定,在计算机内部保存尾数时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。

下面列出了十进制数 178.125 的实数表示。

实数表示 数值
原始十进制数 178.125
二进制数 10110010.001
二进制浮点表示 1.0110010001*2^111
符号 偏移的阶码 有效值
短实数表示 0 0000 0111+0111 1111
=1000 0110
0110 0100 0100 0000 0000 000

注:二进制浮点数的基数是2;基数2的指数111是未偏移的阶码;有效值只保留了尾数的小数部分0110010001。

你也可以编写 java 程序来验证在机器上浮点数是否是以 IEEE754 标准存储的,示例代码如下:

@Test
public void test(){
int i = Float.floatToIntBits(178.125f);
System.out.println(Integer.toBinaryString(i));
//0 10000110 01100100010000000000000
}

推荐文章

[1] 浮点数的二进制表示 阮一峰
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: