二进制中阶码的底也可以不为2。 例如,二进制中阶码的底可以为4、为8等等。 当阶码的底为2,假设阶码为+1,则小数点需要后移一位(即算数左移一位); 当阶码的底为4时,假设阶码为+1,则小数点需要后移两位(即算数左移两位)。 例如: 例题: 如果使用1个字节的空间去存储,那么阶码部分在内存中占3位,位数部分在内存中占5位,刚刚好。 阶码部分在内存中占3位,位数部分在内存中占6位,但是最后一位存不下,只能丢弃掉了。 那么问题来了,如果把最后一个1丢弃了,就意味着b这个浮点数的精度就降低了。 那么能不能把b这个浮点数的表示进行优化,使其在存储空间不变的情况下尽可能地保留它的精度呢? 这个问题就是所谓的浮点数位数规格化的问题。
左规:
以十进制为例: 确保尾数的最高是个有效值。否则可能会丧失精度。
那么现在就把这种思想迁移到二进制的浮点数,比如上面的浮点数b,尾数的第一位0是符号位,必须保留,而小数点后面的这一位也是0,但它是个无效值,所以没有必要保留它,那么怎么处理呢?
可以让尾数部分小数点右移一位(算数左移一位),然后让阶码的值减一即可,此时b的真值是保持不变的,但是由于进行了移位运算,丢弃了最高位无效数值位,所以最低位的空位就可以用来存储原本丢弃的1,这样就可以保证在浮点数整体存储空间不变的情况下,尽可能保留更多的精度。 右规: 规格化浮点数的特点: 例题: 根据上述特点,尾数是负数,所以尾数数值位最高位必须为0,需要把尾数算数左移3位,低位补0,所以规格化的尾数为:1.0100000,因为尾数算数左移了3位(左规),所以阶码需要减3,为:0.011。
为什么要有浮点数的标准?
如果不能确定一个统一的规则, 例如阶码在内存中占多少位? 尾数在内存中占多少位? 各自采用原码、补码还是移码来表示? …… 如果不能没有这样一个统一的规则的话,那么在计算机之间进行数据传输的时候就可能会出现解析方面的困难和问题。
所以IEEE(电气电子工程师协会)就制定了IEEE 754这样一个规则。
1.阶码部分用移码表示,阶码使用移码表示的根本目的在于: 通过加一个固定偏移值使负数转换为正数,使得数值大者其表示的指数也大,但是注意IEEE 754移码偏置值与之前非标准不同了!!! 2.尾数用原码表示,而且尾数部分会隐藏一个表示最高位的1,因为这样的话就免去了尾数规格化的步骤。 例题: 其中移码求法也可以先把阶码真值加上单精度浮点型偏移量的十进制表示,再由十进制转换成二进制原 码,再由原码转换成移码。 最小绝对值与最大绝对值: 若要表示的数绝对值还要更小/更大怎么办?
这就需要用到: IEEE 754小结:
1. C语言的float通常是指IEEE单精确度,而double是指双精确度。
2.为什么c语言中float和int都是32位,但是表示范围不同? float和int都是32位,表示范围不同是因为存储的数类型不同。
浮点类型的单精度值具有4个字节,也就是32位。包括一个符号位、一个8位二进制指数和一个23位尾数。用于存储单精度浮点数或双精度浮点数。提供了一个大约在 -3.4E+38 ~ 3.4E+38 之间的范围。
(e为实型数据的指数表示形式,其中,e的前后必须要有数字,e前面为十进制数,e后面为十进制整数,可以带符号。)
int类型在内存中占用了4个字节,也就是32位。int类型是有符号的,因此,32位并不会全部用来存储数据,包括一个符号位,使用其他的31位来存储数据。用于存储整数类型变量。-2147483648 ~ 2147483647[-2^31 ~ 2^31-1]。
3.为什么c语言中long和int都是32位,但是long的表示范围更大? C语言开始时只有char(8位)和int(16位)两种,后来随着发展又加入了short(16位)和long(32位),此时,int可以是16位或者32位,依赖于平台和后续的兼容性。再后来当64位出现时,long long(64位)又被添加进来,为了进行规范,对较小的一些类型的范围就有了一些调整,逐渐稳定为int32位,long可以有多种定义,可以是32位,也可以是64位。
C++标准上只是说long至少要和int一样大,所有整数类型实现时要满足如下规范: sizeof(char) == 1 sizeof(char) <= sizeof(short) sizeof(short) <= sizeof(int) sizeof(int) <= sizeof(long) sizeof(long) <= sizeof(long long)