计算机对外信息展现方式有文字、图片、音频、视频等,但不论应用在什么地方,信息在机器内部的形式都是一致的,即均为0和1组成的各类编码。html
在计算机中参与运算的数有两大类:无符号数和有符号数。java
计算机中的数均放在寄存器中,一般称寄存器的位数为机器字长。编程
所谓无符号数,即没有符号的数,在寄存器中的每一位都可用来存放数值。当存放有符号数时,则需留出位置存放符号。编码
所以,在机器字长相同时,无符号数与有符号数所对应的数值范围是不一样的。3d
以机器字长为16位为例,无符号数的表示范围为 0~65535,而有符号数的表示范围为 -32768 ~ +32767(此数值对应补码表示)。code
对有符号数而言,符号的“正”、“负”机器是没法识别的,但因为“正”、“负”刚好是两种大相径庭的状态,若是用“0“表示“正”,用“1”表示“负”,这样符号也被数字化了,而且规定将它放在有效数字的前面,即组成了有符号数。
例如,+1100 在机器中表示为 01100 ,-1100 在机器中表示为 1 1100 。视频
在Java语言中,如 int、float 等都是有符号数,故下文所讲都是在有符号数的范畴。htm
把符号(如+、-)“数字化”的数称为机器数,而把带“+”或“-”符号的数称为真值。blog
一旦符号数字化后,符号和数值就造成了一种新的编码。在运算过程当中,符号位可否和数值部分一块儿参加运算?若是参加运算,符号位又需做哪些处理?这些问题都与符号位和数值位所构成的编码有关,这些编码就是原码、补码、反码和移码。图片
原码是机器数中最简单的一种表示形式,符号位为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,四、8或16等。
浮点数的规格化形式为 N = 0.110101 * 2^10。
浮点数在机器中的形式以下所示。
浮点数由阶码j和尾数S两部分组成。阶符表示阶码数值部分的正负,数符表示尾数数值部分的正负。阶码j反映了浮点数的表示范围及小数点的实际位置。尾数是小数,其位数n反映了浮点数的精度。
定点数和浮点数可从以下几个方面进行比较。
①当浮点机和定点机中数的位数相同时,浮点数的表示范围比定点数的大得多。
②当浮点数为规格化数时,其相对精度远比定点数高。
③浮点数运算要分阶码部分和尾数部分,并且运算结果都要求规格化,故浮点运算步骤比定点运算步骤多,运算速度比定点运算的低,运算线路比定点运算的复杂。
④在溢出的判断方法上,浮点数是对规格化数的阶码进行判断,而定点数是对数值自己进行判断。例如小数定点机中的数其绝对值必须小于1,不然“溢出”,此时要求机器中止运算,进行处理。为了防止溢出,上机前必须选择比例因子,这个工做比较麻烦给编程带来不便。而浮点数的表示范围远比定点数大,仅当“上溢”时机器才中止运算,故通常没必要考虑比例因子的选择。
总之,浮点数在数的表示范围、数的精度、溢出处理和程序编程方面(不取比例因子)均优于定点数。但在运算规则、运算速度及硬件成本方面又不如定点数。所以,究竟选用定点数仍是浮点数,应根据具体应用综合考虑。通常来讲,通用的大型计算机大多采用浮点数,或同时采用定、浮点数;小型、微型及某些专用机、控制机则大多采用定点数。当须要做浮点运算时,可经过软件实现,也可外加浮点扩展硬件(如协处理器)来实现。
现代计算机中,浮点数通常采用 IEEE 制定的国际标准,这种标准形式以下:
按 IEEE 标准,经常使用的浮点数有三种:
符号位S | 阶码 | 尾数 | 总位数 | |
---|---|---|---|---|
短实数 | 1 | 8 | 23 | 32 |
长实数 | 1 | 11 | 52 | 64 |
临时实数 | 1 | 15 | 64 | 80 |
其中,S为数符,表示浮点数的正负,但与其有效位(尾数)是分开的。
阶码的真值都被加上一个常数(偏移量),如短实数、长实数和临时实数的偏移量用十进制数表示分别为 12七、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] 浮点数的二进制表示 阮一峰