精华内容
下载资源
问答
  • 浮点数

    2020-04-02 22:16:51
    浮点数基本格式浮点数的表示格式化表示范围IEEE 754标准 基本格式 浮点数的表示 r进制: 定点数:如纯小数0.1011和纯整数11110 浮点数浮点数的真值: 阶码(E): 常用补码或移码表示 反映浮点数的表示范围及...

    基本格式

    浮点数的表示

    r进制:在这里插入图片描述
    定点数:如纯小数0.1011和纯整数11110
    浮点数:
    在这里插入图片描述

    • 浮点数的真值:在这里插入图片描述
    • 阶码(E):
      • 常用补码或移码表示
      • 反映浮点数的表示范围及小数点的实际位置
    • 尾数(M):常用原码或补码表示
      • 数值部分的位数n反映浮点数的精度

    十进制:

    299792458m/s =2.998*108 m/s
    定点数 浮点数
    需要9个数据的位 需要5个数据的位(会损失精度)

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    由上图可知,b需要9位,而只能提供8位,所以需要进行规格化
    在这里插入图片描述

    格式化

    规格化:规定尾数的最高位必须是一个有效值。对于二进制来说,要求最高位是1;对于其他进制来说,要求最高位非0
    在这里插入图片描述

    表示范围

    在这里插入图片描述
    (n 为尾数的尾数)
    在这里插入图片描述
    (负数由原码取反+1得来的)
    在这里插入图片描述
    小数就是以上向右移2位,即除以4得
    在这里插入图片描述
    在这里插入图片描述
    正上溢和负上溢会错误中断
    在这里插入图片描述

    IEEE 754标准

    在这里插入图片描述
    数符:决定整个数的正负
    隐藏表示最高位1放在小数点左边,尾数放在右边,因为规格化后尾数的最高位为1,为节约空间,故省去
    在这里插入图片描述
    建议采取空间记忆
    1000 0001 1100 1010 0101 0000 1000 0000
    依次为:数符 阶码 尾数数值
    偏置值:阶码10000000-1=01111111=127(阶码最高位为1,后面全为0,减去1得到的值为偏置值)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • IEEE754 浮点数的表示方法

    万次阅读 多人点赞 2016-01-09 17:08:19
    1.浮点数的存储格式 浮点数在C/C++中对应float和double类型,我们有必要知道浮点数在计算机中实际存储的内容。 IEEE754标准中规定float单精度浮点数在机器中表示用 1 位表示数字的符号,用 8 位来表示指数,用...

    1.浮点数的存储格式

    浮点数(Floating-point Number)是对实数的一种近似表示,由一个有效数字(即尾数)加上幂数来表示,通常是乘以某个基数的整数次幂得到。以这种表示法表示的数值,称为浮点数。表示方法类似于基数为10的科学计数法。利用浮点进行运算,称为浮点计算,这种运算通常伴随着因为无法精确表示而进行的近似或舍入。

    计算机对浮点数的表示规范遵循电气和电子工程师协会(IEEE)推出的 IEEE754 标准,浮点数在 C/C++ 中对应 float 和 double 类型,我们有必要知道浮点数在计算机中实际存储的内容。

    IEEE754 标准中规定 float 单精度浮点数在机器中表示用 1 位表示数字的符号,用 8 位表示指数,用 23 位表示尾数,即小数部分。对于 double 双精度浮点数,用 1 位表示符号,用 11 位表示指数,52 位表示尾数,其中指数域称为阶码。IEEE754 浮点数的格式如下图所示。
    这里写图片描述
    注意,IEE754 规定浮点数阶码 E 采用"指数e的移码-1"来表示,请记住这一点。为什么指数移码要减去 1,这是 IEEE754 对阶码的特殊要求,以满足特殊情况,比如对正无穷的表示。

    2.移码

    移码(又叫增码)是对真值补码的符号位取反,一般用作浮点数的阶码,引入的目的是便于浮点数运算时的对阶操作。

    对于定点整数,计算机一般采用补码的来存储。正整数的符号位为 0,反码和补码等同于原码。负整数符号位为1,原码、反码和补码的表示都不相同,由原码变成反码和补码有如下规则:
    (1)原码符号位为1不变,整数的每一位二进制数位求反得反码;
    (2)反码符号位为1不变,反码数值位最低位加1得补码。

    比如,以一个字节 8bits 来表示 -3,那么[−3]原=10000011[-3]_原=10000011[3]=10000011[−3]反=11111100[-3]_反=11111100[3]=11111100[−3]补=11111101[-3]_补=11111101[3]=11111101,那么 -3 的移码就是[−3]移=01111101[-3]_移=01111101[3]=01111101

    如何将移码转换为真值 -3 呢?先将移码转换为补码,再求值。

    3.浮点数的规格化

    若不对浮点数的表示作出明确的规定,同一个浮点数的表示就不是唯一的。例如(1.75)10(1.75)_{10}(1.75)10可以表示成1.11×201.11\times 2^01.11×200.111×210.111\times2^10.111×210.0111×220.0111\times2^20.0111×22等多种形式。当尾数不为0时,尾数域的最高有效位为1,这称为浮点数的规格化。否则,以修改阶码同时左右移动小数点位置的办法,使其成为规格化数的形式。

    3.1 单精度浮点数真值

    IEEE754 标准中,一个规格化的 32 位浮点数 x 的真值表示为:
    x=(−1)S×(1.M)×2ex=(-1)^S\times(1.M)\times2^ex=(1)S×(1.M)×2e
    e=E−127e=E-127e=E127
    其中尾数域值是1.M。因为规格化的浮点数的尾数域最左位总是1,故这一位不予存储,而认为隐藏在小数点的左边。

    在计算指数 e 时,对阶码E的计算采用原码的计算方式,因此 32 位浮点数的 8bits 的阶码 E 的取值范围是 0 到 255。其中当E为全 0 或者全 1 时,是 IEEE754 规定的特殊情况,下文会另外说明。

    3.2 双精度浮点数真值

    64 位的浮点数中符号为 1 位,阶码域为 11 位,尾数域为 52 位,指数偏移值是 1023。因此规格化的 64 位浮点数 x 的真值是:
    x=(−1)S×(1.M)×2ex=(-1)^S\times(1.M)\times2^ex=(1)S×(1.M)×2e
    e=E−1023e=E-1023e=E1023

    4.浮点数的具体表示

    4.1 十进制到机器码

    (1)0.5
    0.5=(0.1)20.5=(0.1)_20.5=(0.1)2,符号位S为0,指数为e=−1e=-1e=1,规格化后尾数为1.0。

    单精度浮点数尾数域共23位,右侧以0补全,尾数域:
    M=[000 0000 0000 0000 0000 0000]2M=[000\ 0000\ 0000\ 0000\ 0000\ 0000]_2M=[000 0000 0000 0000 0000 0000]2

    阶码E:
    E=[−1]移−1=[0111 1111]2−1=[0111 1110]2E=[-1]_移-1=[0111\ 1111]_2-1=[0111\ 1110]_2E=[1]1=[0111 1111]21=[0111 1110]2

    对照单精度浮点数的存储格式,将符号位S,阶码E和尾数域M存放到指定位置,得0.5的机器码:
    0.5=[0011 1111 0000 0000 0000 0000 0000 0000]20.5=[0011\ 1111\ 0000\ 0000\ 0000\ 0000\ 0000\ 0000]_20.5=[0011 1111 0000 0000 0000 0000 0000 0000]2

    十六进制表示为0.5=0x3f000000。

    (2)1.5
    1.5=[1.1]21.5=[1.1]_21.5=[1.1]2,符号位为0,指数e=0e=0e=0,规格化后尾数为1.1。

    尾数域M右侧以0补全,得尾数域:
    M=[100 0000 0000 0000 0000 0000]2M=[100\ 0000\ 0000\ 0000\ 0000\ 0000]_2M=[100 0000 0000 0000 0000 0000]2

    阶码E:
    E=[0]移−1=[10000000]2−1=[01111111]2E=[0]_移-1=[1000 0000]_2-1=[0111 1111]_2E=[]1=[10000000]21=[01111111]2

    得1.5的机器码:
    1.5=[0011 1111 1100 0000 0000 0000 0000 0000]21.5=[0011\ 1111\ 1100\ 0000\ 0000\ 0000\ 0000\ 0000]_21.5=[0011 1111 1100 0000 0000 0000 0000 0000]2

    十六进制表示为1.5=0x3fc00000。

    (3)-12.5
    −12.5=[−1100.1]2-12.5=[-1100.1]_212.5=[1100.1]2,符号位S为1,指数e为3,规格化后尾数为1.1001,

    尾数域M右侧以0补全,得尾数域:
    M=[100 1000 0000 0000 0000 0000]2M=[100\ 1000\ 0000\ 0000\ 0000\ 0000]_2M=[100 1000 0000 0000 0000 0000]2

    阶码E:
    E=[3]移−1=[1000 0011]2−1=[1000 0010]2E=[3]_移-1=[1000\ 0011]_2-1=[1000\ 0010]_2E=[3]1=[1000 0011]21=[1000 0010]2

    即-12.5的机器码:
    −12.5=[1100 0001 0100 1000 0000 0000 0000 0000]2-12.5=[1100\ 0001\ 0100\ 1000\ 0000\ 0000\ 0000\ 0000]_212.5=[1100 0001 0100 1000 0000 0000 0000 0000]2

    十六进制表示为-12.5=0xc1480000。

    用如下程序验证上面的推算,代码编译运行平台Win32+VC++ 2012:

    #include <iostream>
    using namespace std;
    
    int main() {
    	float a=0.5;
    	float b=1.5;
    	float c=-12.5;
    
    	unsigned int* pa=NULL;
    	pa=(unsigned int*)&a;
    	unsigned int* pb=NULL;
    	pb=(unsigned int*)&b;
    	unsigned int* pc=NULL;
    	pc=(unsigned int*)&c;
    	
    	cout<<hex<<"a=0x"<<*pa<<endl;
    	cout<<hex<<"b=0x"<<*pb<<endl;
    	cout<<hex<<"c=0x"<<*pc<<endl;
    	
    	return 0;
    }
    

    输出结果:

    a=0x3f000000
    b=0x3fc00000
    c=0xc1480000
    

    验证正确。

    4.2 机器码到十进制

    (1)若浮点数 x 的 IEEE754 标准存储格式为 0x41360000,那么其浮点数的十进制数值的推演过程如下:

    0x41360000=[0 10000010 011 0110 0000 0000 0000 0000]0x41360000=[0\ 10000010\ 011\ 0110\ 0000\ 0000\ 0000\ 0000]0x41360000=[0 10000010 011 0110 0000 0000 0000 0000]

    根据该浮点数的机器码得到符号位 S=0,指数 e=阶码-127=1000 0010-127=130-127=3

    注意,根据阶码求指数时,可以像上面直接通过 "阶码-127"求得指数e,也可以将阶码+1=移码阶码+1=移码+1=,再通过移码求其真值便是指数 e。比如上面阶码 10000010+1=10000011[移码]=>00000011[补]=3(指数e)10000010+1=10000011_{[移码]}=>00000011_{[补]}=3(指数e)10000010+1=10000011[]=>00000011[]=3(e)

    包括尾数域最左边的隐藏位1,那么尾数 1.M=1.011 0110 0000 0000 0000 0000=1.011011。

    于是有:
    x=(−1)S×1.M×2e=+(1.011011)×23=+1011.011=(11.375)10x=(-1)^S\times1.M\times2^e=+(1.011011)\times2^3=+1011.011=(11.375)_{10}x=(1)S×1.M×2e=+(1.011011)×23=+1011.011=(11.375)10

    通过代码同样可以验证上面的推算:

    #include <iostream>
    using namespace std;
    
    int main() {
    	unsigned int hex=0x41360000;
    	float* fp=(float*)&hex;
    	cout<<"x="<<*fp<<endl;
    	return 0;
    }
    

    输出结果:

    x=11.375
    

    验证正确。

    5.浮点数的几种特殊情况

    (1)0 的表示
    对于阶码为 0 或 255 的情况,IEEE754 标准有特别的规定:
    如果 阶码 E=0 并且尾数 M 是 0,则这个数的真值为 ±0(正负号和数符位有关)。

    因此 +0 的机器码为:0 00000000 000 0000 0000 0000 0000 0000。
    -0 的机器码为:1 00000000 000 0000 0000 0000 0000 0000。

    需要注意一点,浮点数不能精确表示 0,而是以很小的数来近似表示 0,因为浮点数的真值等于(以32bits单精度浮点数为例):
    x=(−1)S×(1.M)×2ex=(-1)^S\times(1.M)\times2^ex=(1)S×(1.M)×2e
    e=E−127e=E-127e=E127
    那么 +0 的机器码对应的真值为1.0×2−1271.0\times2^{-127}1.0×2127。同理,-0 机器码真值为−1.0×2−127-1.0\times2^{-127}1.0×2127

    (2)+∞+\infty+−∞-\infty 的表示
    如果阶码 E=255 并且尾数 M 全是0,则这个数的真值为 ±∞(同样和符号位有关)。因此+∞+\infty+的机器码为:0 11111111 000 0000 0000 0000 0000 0000。−∞-\infty的机器吗为:1 11111111 000 0000 0000 0000 0000 0000。

    (3)NaN(Not a Number)
    如果 E = 255 并且 M 不是0,则这不是一个数(NaN)。

    6.浮点数的精度和数值范围

    6.1 浮点数的数值范围

    根据上面的探讨,浮点数可以表示-∞到+∞,这只是一种特殊情况,显然不是我们想要的数值范围。

    以 32 位单精度浮点数为例,阶码 E 由 8 位表示,取值范围为 0-255,去除 0 和 255 这两种特殊情况,那么指数 e 的取值范围就是 1-127=-126 到 254-127=127。

    (1)最大正数
    因此单精度浮点数最大正数值的符号位S=0,阶码E=254,指数e=254-127=127,尾数M=111 1111 1111 1111 1111 1111,其机器码为:0 11111110 111 1111 1111 1111 1111 1111。

    那么最大正数值:
    PosMax=(−1)S×1.M×2e=+(1.11111111111111111111111)×2127≈3.402823e+38PosMax=(-1)^S\times1.M\times2^e=+(1.111 1111 1111 1111 1111 1111)\times2^{127}\approx3.402823e+38PosMax=(1)S×1.M×2e=+(1.11111111111111111111111)×21273.402823e+38
    这是一个很大的数。

    (2)最小正数
    最小正数符号位S=0,阶码E=1,指数e=1-127=-126,尾数M=0,其机器码为0 00000001 000 0000 0000 0000 0000 0000。

    那么最小正数为:
    PosMin=(−1)S×1.M×2e=+(1.0)×2−126≈1.175494e−38PosMin=(-1)^S\times1.M\times2^e=+(1.0)\times2^{-126} \approx1.175494e-38PosMin=(1)S×1.M×2e=+(1.0)×21261.175494e38

    这是一个相当小的数。几乎可以近似等于0。当阶码E=0,指数为-127时,IEEE754就是这么规定1.0×2−1271.0\times2^{-127}1.0×2127近似为0的,事实上,它并不等于0。

    (3)最大负数
    最大负数符号位S=1,阶码E=1,指数e=1-127==-126,尾数M=0,机器码与最小正数的符号位相反,其他均相同,为:1 00000001 000 0000 0000 0000 0000 0000。

    最大负数等于:
    NegMax=(−1)S×1.M×2e=−(1.0)×2−126≈−1.175494e−38NegMax=(-1)^S\times1.M\times2^e=-(1.0)\times2^{-126} \approx-1.175494e-38NegMax=(1)S×1.M×2e=(1.0)×21261.175494e38

    (4)最小负数
    符号位S=0,阶码E=254,指数e=254-127=127,尾数M=111 1111 1111 1111 1111 1111,其机器码为:1 11111110 111 1111 1111 1111 1111 1111。

    计算得:
    NegMin=(−1)S×1.M×2e=+(1.11111111111111111111111)×2127=−3.402823e+38NegMin=(-1)^S\times1.M\times2^e=+(1.111 1111 1111 1111 1111 1111)\times2^{127}=-3.402823e+38NegMin=(1)S×1.M×2e=+(1.11111111111111111111111)×2127=3.402823e+38

    6.2 浮点数的精度

    说到浮点数的精度,先给精度下一个定义。浮点数的精度是指浮点数的小数位所能表达的位数。

    阶码的二进制位数决定浮点数的表示范围,尾数的二进制位数表示浮点数的精度。以 32 位浮点数为例,尾数域有 23 位。那么浮点数以二进制表示的话精度是 23 位,23 位所能表示的最大数是223−1=83886072^{23}-1=83886072231=8388607,所以十进制的尾数部分最大数值是 8388607,也就是说尾数数值超过这个值,float 将无法精确表示,所以 float 最多能表示小数点后 7 位,但绝对能保证的为 6 位,即 float 的十进制的精度为 6~7 位。

    64 位双精度浮点数的尾数域 52 位,因252−1=4,503,599,627,370,4952^{52}-1=4,503,599,627,370,4952521=4,503,599,627,370,495,所以双精度浮点数的十进制的精度最高为 16 位,绝对保证的为 15 位,所以 double 的十进制的精度为 15~16 位。

    7.小结

    本文操之过急,难免出现编辑错误和不当说法,请网友批评指正。不明之处,欢迎留言交流。对浮点数的加减乘除运算还未涉及,后续可能会去学习并记录学习所得,与大家分享。


    参考文献

    [1] 百度百科.移码
    [2] 百度知道.关于IEEE754标准浮点数阶码的移码
    [3] 白中英.计算机组成原理第四版[M].科学出版社:P16-30
    [4] 维基百科.浮点数

    展开全文
  • C语言浮点数

    万次阅读 多人点赞 2019-08-03 20:23:07
    浮点数的概念 浮点数也称小数或实数。例如,0.0、75.0、4.023、0.27、-937.198 都是合法的小数。这是常见的小数的表现形式,称为十进制形式。 C语言中采用float和double关键字来定义小数,float称为单精度浮点型...

     

    浮点数的概念

           浮点数也称小数或实数。例如,0.0、75.0、4.023、0.27、-937.198 都是合法的小数。这是常见的小数的表现形式,称为十进制形式。

           C语言中采用float和double关键字来定义小数,float称为单精度浮点型,double称为双精度浮点型,long double更长的双精度浮点型。

           在任何区间内(如1.0 到 2.0 之间)都存在无穷多个实数,计算机的浮点数不能表示区间内所有的值。浮点数通常只是实际值的近似值,例如7.0可能被储存为浮点值6.99999。

    点用内存的情况

           我们先来测试一下float、double和long double三种浮点数据类型占用内存的字节数。

           示例(book71.c)

           

           运行结果

           

    浮点数的精度

           C标准规定,float类型必须至少能表示6位有效数字,且取值范围至少是10-37~10+37。

           double类型和 float类型的最小取值范围相同,但至少必须能表示10位有效数字。

           long double,以满足比double类型更高的精度要求。不过,C只保证long double类型至少与double类型的精度相同。

           看了上面这段文字,估计大家有点晕,在之前的整数章节中,long比int的占用的内存多,存放数据的值也就越大,并且有一个准确的范围,但是,为什么各种浮点数存放数据的值怎么就这么模糊呢?我先不解释原因,浮点数的存储方式比较复杂,暂时不讨论,先用几个程序来测试一下它们的特征。

    1、测试float类型

           示例(book73.c)

           

           运行结果

           

           从程序的运行我们可以看出float数的两个特征:

           1)float数据类型表达的是一个近似的数,不是准确的,小数点后的n位有误差,浮点数的位数越大,误差越大,到8位的时候,误差了1,基本上不能用了。

           2)用“==”可以比较两个整数或字符是否相等,但是,看起来相等的两个浮点数,就是不会相等。

    2、测试double类型

           示例(book74.c)

           

           运行结果

           

           从程序的运行我们可以看出double数的两个特征:

           1)double数据类型表达的也是一个近似的数,不是准确的,小数点后的n位有误差,浮点数的位数越大,误差越大,到17位的时候,误差了1,基本上不能用了。

           2)用“==”可以比较两个double数值是否相等。

    3、测试long double类型

           示例(book75.c)

           

           运行结果

           

           long double的测试结果与double相同。

    4、测试总结

          float只能表达6-7位的有效数字,不能用“==”判断两个数字是否相等。

          double能表达15-16位有效的数字,可以用“==”判断两个数字是否相等。

          long double和double的特征相同。

          在实际开发中,建议弃用float,只采用double就可以,long double暂时没有必要,但不知道以后的操作系统和编译器对long double是否有改进。

    浮点数的输出

          float采用%f输出,double采用%lf输出,测试结果证明,double也可以采用%f输出。

          long double采用%Lf输出,注意,L是大写。

          %lf缺省显示小数点后六位。

          如果要显示小数点后n位,用%.nlf,例如:

          double ff=7.5;

          %.2lf  显示 7.50

          浮点数采用%lf输出,完整的输出格式是%m.nlf,指定输出数据整数部分和小数部分共占m位,其中有n位是小数。如果数值长度小于m,则左端补空格,若数值长度大于m,则按实际位数输出。

    常用的库函数

          在接下来的内容中,我只介绍double,不再介绍float和long double两种数据类型相关的知识。

          以下是常用的浮点数函数,必须掌握。

          double atof(const char *nptr);       // 把字符串nptr转换为double

          double fabs(double x);               // 求双精度实数x的绝对值

          double pow(double x, double y);     // 求 x 的 y 次幂(次方)

          double round(double x);              // double四舍五入

          double ceil(double x);                 // double向上取整数

          double floor(double x);               // double向下取整数

          double fmod(double x,double y);     // 求x/y整除后的双精度余数

          double modf(double val,double *ip); // 把双精度val分解成整数部分和小数部分,整数部分存放在ip所指的变量中,返回小数部分。

          还有一些数据计算函数,如正弦、对数、指数等,实际开发中极少使用,大家要用的时候再查资料,我就不介绍了。

    整数转换为浮点数

          我们先来看一个示例(book77.c):

           

          运行结果

           

          需要特别注意的是dd=ii/jj这一行代码,dd的值0,不是0.75,有点意外,所以,如果对整数转换为浮点数没有把握,加(double)强制转换是个好办法。

    应用技巧

          浮点数有一些坑,例如两个浮点数不相等和精度的问题,在实际开发中,我们经常用整数代替浮点数,因为整数是精确的,效率也更高。

          例如人的身高一米七五,以米为单位,用浮点数表示是1.75米,如果以厘米为单位,用整数表示是175。

          long整数的取值是-9223372036854775808~9223372036854775807,有效数字是19位,而double的有效数字才15-16位,所以,整数可以表达的小数更大的数,更实用,麻烦也更少。

          货币:1.75元,如果采用0.01元为单位就是175,采用0.001元为单位就是1750,如果你说要更多小数怎么办?你这是钻牛角尖。

          给大家说一个道,高水平的程序员不容易掉坑里,注意,是不容易,不是一定不会,最好的方法是没有坑。

    科学计数法

          在实际开发中,我们很少使用科学计数法,但是它经常出现在计算机系统中,例如浮点数在内存中的存放方式就是科学计数法,所以我们还是有必要学习科学计数法。

          科学记数法是一种记数的方法。把一个数表示成a与10的n次幂相乘的形式(1≤|a|<10,n为整数),这种记数法叫做科学记数法。当我们要书写或运算某个较大或较小且位数较多时,用科学记数法免去浪费很多空间和时间。

          例如:51400000000=5.14×1011。计算器或电脑表达10的幂是一般是用E或e,也就是51400000000=5.14E11或5.14e11。

          用科学记数法表示数时,不改变数的符号,只是改变数的书写形式而已,可以方便的表示日常生活中遇到的一些极大或极小的数 。如:光的速度大约是300,000,000米/秒;全世界人口数大约是:6,100,000,000。

          这样的数,书写和显示都很不方便,我们可以免去写这么多重复的0,将其表现为这样的形式:6,100,000,000=6.1×109,即6.1E9或6.1e9。

          或:0.00001=1×10-5,即绝对值小于1的数也可以用科学记数法表示为a乘10 的负n次方的形式。即1E-5或1e-5。

          科学计数法采用%e或%E输出,完整的输出格式是%m.ne或%m.nE,指定输出数据整数部分和小数部分共占m位,其中有n位是小数。如果数值长度小于m,则左端补空格,若数值长度大于m,则按实际位数输出。

          示例(book78.c):

           

          运行结果

           

     

    版权声明

    C语言技术网原创文章,转载请说明文章的来源、作者和原文的链接。

    来源:C语言技术网(www.freecplus.net

    作者:码农有道

    如果这篇文章对您有帮助,请点赞支持,或在您的博客中转发我的文章,谢谢!!!

    如果文章有错别字,或者内容有误,或其他的建议或意见,请您留言指正,非常感谢!!!

     

    展开全文
  • 浮点数表示

    万次阅读 多人点赞 2016-12-22 15:00:17
    之前的一些工作当中碰到了很多有关浮点数的问题,比如浮点数的表达范围、表达精度、浮点数的存储方式、浮点数的强制类型转换等等,因此感觉有必要系统了解一下有关浮点数的问题。 —————————— 浮点数表示 ...

    之前的一些工作当中碰到了很多有关浮点数的问题,比如浮点数的表达范围、表达精度、浮点数的存储方式、浮点数的强制类型转换等等,因此感觉有必要系统了解一下有关浮点数的问题。

    —————————— 浮点数表示 ——————————

    浮点数是一种 公式化 的表达方式,用来近似表示实数,并且可以在表达范围和表示精度之间进行权衡(因此被称为浮点数)。

    浮点数通常被表示为:

    \(N = M\times R^E\)

    比如: \(12.345 = 1.2345\times 10^1\)

    其中,M(Mantissa)被称为浮点数的 尾数 ,R(Radix)被称为阶码的 基数 ,E(Exponent)被称为阶的 阶码 。计算机中一般规定R为2、8或16,是一个确定的常数,不需要在浮点数中明确表示出来。

    因此,在已知标准下,要表示浮点数,

    一是要给出尾数M的值,通常用定点小数形式表示,它决定了浮点数的表示精度,即可以给出的有效数字的位数。

    二是要给出阶码,通常用定点整数形式表示,它指出的是小数点在数据中的位置,决定了浮点数的表示范围。因此,在计算机中,浮点数通常被表示成如下格式:(假定为32位浮点数,基为2,其中最高位为符号位)

    浮点数

    —————————— 浮点数的规格化表示 ——————————

    按照上面的指数表示方法,一个浮点数会有不同的表示:

    \(0.3\times10^0\);\(0.03\times10^1\);\(0.003\times10^2\);\(0.0003\times10^3\);

    为了提高数据的表示精度同时保证数据表示的唯一性,需要对浮点数做规格化处理。

    在计算机内,对非0值的浮点数,要求尾数的绝对值必须大于基数的倒数,即\(|M|\ge \frac{1}{R}\)。

    即要求尾数域的最高有效位应为1,称满足这种表示要求的浮点数为规格化表示:把不满足这一表示要求的尾数,变成满足这一要求的尾数的操作过程,叫作浮点数的规格化处理,通过尾数移位和修改阶码实现。

    比如,二进制原码的规格化数的表现形式:(0正1负)

    正数 0.1xxxxxx

    负数 1.1xxxxxx

    注意,尾数的最高位始终是1,因此我们完全可以省略掉该位。

    至此,我们引入IEEE754 标准,该标准约束了浮点数的大部分使用设置:(尾数用原码;阶码用“移码”;基为2)

    (1) 尾数用原码,且隐藏尾数最高位。

    原码非0值浮点数的尾数数值最高位必定为 1,因此可以忽略掉该位,这样用同样多的位数就能多存一位二进制数,有利于提高数据表示精度,称这种处理方案使用了隐藏位技术。当然,在取回这样的浮点数到运算器执行运算时,必须先恢复该隐藏位。

    (2) 阶码使用“移码”,基固定为2

    如下图的32bit浮点数和64bit浮点数,从最高位依次是符号位、阶码和尾数
    float

    于是,

    一个规格化的32位浮点数x的真值为:

    \(x = (-1)^s\times(1.M)\times2^{E-127}\)

    一个规格化的64位浮点数x的真值为:

    \(x = (-1)^s\times(1.M)\times2^{E-1023}\)

    下面举一个32位单精度浮点数-3.75表示的例子帮助理解:

    (1) 首先转化为2进制表示

    \(-3.75 = -(2+1+1/2+1/4) = -1.111\times2^1\)

    (2) 整理符号位并进行规格化表示

    \(-1.111\times2^1 = (-1)^{(1)}\times(1+0.1110\ 0000\ 0000\ 0000\ 0000\ 000)\times2^1\)

    (3) 进行阶码的移码处理
    \((-1)^{(1)}\times(1+0.1110\ 0000\ 0000\ 0000\ 0000\ 000)\times2^1\)
    \(=(-1)^{(1)}\times(1+0.1110\ 0000\ 0000\ 0000\ 0000\ 000)\times2^{128-127}\)

    于是,符号位S=1,尾数M为\(1110\ 0000\ 0000\ 0000\ 0000\ 000\)阶码E为\(128_{10}=1000\ 0000_2\),则最终的32位单精度浮点数为

    \(1\ 1110\ 0000\ 0000\ 0000\ 0000\ 000\ 1000\ 0000\)

    —————————— 浮点数的表示范围 ——————————

    通过上面的规格化表示,我们可以很容易确定浮点数的表示范围:

    float range

    既然有表示范围,那肯定也有不能表示的数值:
    首先来说明溢出值,如下图:
    float overflow

    (1)无穷值:

    如果指数\(E=11111111_2=255_{10}\)且尾数\(M=0\),则根据符号位S分别表示\(+\infty\)和\(-\infty\)。因此,一个有效的32位浮点数其指数最大只能为254。

    此外,无穷具有传递性,比如

    (+∞) + (+7) = (+∞)

    (+∞) × (−2) = (−∞)

    (+∞) × 0 = NaN

    (2)零值:

    如果指数\(E=0\)且尾数\(M=0\)时,表示机器0.需要注意的是,这里的0也是有符号的,在数值比较的时候 \(+0=-0\); 但在一些特殊操作下,二者并不显相等,比如\(\log(x)\), \(\frac{1}{+0} \neq \frac{1}{-0}\)。

    此外,处于负下溢出和负上溢出之间的数值会被直接归为0。

    (3)NAN:

    如果\(E=0\)且尾数\(M\neq 0\),则表示这个值不是一个真正的值(Not A Number)。NAN又分成两类:QNAN(Quiet NAN)和SNAN(Singaling NAN)。QNAN与SNAN的不同之处在于,QNAN的尾数部分最高位定义为1,SNAN最高位定义为0;QNAN一般表示未定义的算术运算结果,如\(\frac{0}{0}\), \(\infty \times 0\), \(sqrt(-1)\);SNAN一般被用于标记未初始化的值,以此来捕获异常。

    —————————— 浮点数的表示精度 ——————

    一般提到浮点数的精度(有效位数)的时候,总是会出现 float的有效位为6~7位, double的有效位为15~16位

    下面以float为例,解释一下有效位数是怎样来的。

    有效位数只和规格化浮点数的尾数部分有关,而尾数部分的位数是23位,因此我们首先列出下表

    float overflow

    由上面的表格可以看出:

    \(2^{-23}\) 和 \(2^{-22}\) 之间是存在间隔的,即0.0000001和0.0000002之间的小数我们是没有办法描述的,因此23位尾数最多只能描述到小数点后第7位;此外,我们通过四舍五入可以很容易发现\(0.0000003 = 0.0000004 = 2^{-23}+2^{-22}\), 这表明第7位有效数字只是部分准确。而第6位及之前的都是可以准确描述的,因此我们说float的有效位为6~7位。

    —————————— 参考资料 ——————————

    (1) WIKI 词条 “Floating Point”: https://en.wikipedia.org/wiki/Floating_point

    (2) WIKI 词条 “IEEE floating point”: https://en.wikipedia.org/wiki/IEEE_floating_point

    (2) 浮点异常值:NAN,QNAN,SNAN:
    http://www.cnblogs.com/konlil/archive/2011/07/06/2099646.html

    展开全文
  • 浮点数的表示方法

    万次阅读 多人点赞 2019-02-13 23:44:28
    把一个数的有效数字和数的范围在计算机的一个存储...其中M称为浮点数的尾数,是一个纯小数。e是比例因子的指数,称为浮点数的指数,是一个整数。比例因子的基数2对二进记数制的机器是一个常数。 在机器中表示一个...
  • 在我的计算机科学课程中,我们正在研究浮点数及其在内存中的表示方式。我已经了解了它们在内存中的表示方式(尾数/有效数,指数及其偏倚以及符号位),并且我了解了浮点数是如何相互加减的(非正规化和所有这些有趣的...
  • 浮点数构成

    2018-05-15 20:02:24
    一般在写一些静态类型的语言的时候(c , golang等等),通常会提供一种单精度浮点数的数据类型,float(float32),这篇博文主要讲解单精度浮点数,对于双精度浮点数在构造上实际上与单精度浮点数差不了多少,懂了...
  • 本文档简介了TMS320C3x浮点数简介、IEEE754的32位转VC33的32位浮点数算法、IEEE754的64位浮点数转VC33的40位浮点数算法;给相关TI的DSP开发工程师提供开发参考。
  • 浮点数小记

    2020-06-25 15:29:02
    浮点数float分为 半精度浮点数(16位)、单精度浮点数(32位)以及双精度浮点数(64位)。 浮点数由符号位(signed)、指数位(Exponent)、尾数位(Mantissa)以及基数构成,二进制浮点数基数是2,十进制浮点数基数...
  • 单片机浮点数设计 单片机浮点数设计 单片机浮点数设计
  • 浮点数运算案例

    千次阅读 2020-03-31 17:35:24
    浮点数运算案例
  • 说明:%3.0f表明待打印的浮点数(floatNum)至少占3个字符宽,且不带小数点和小数部分,整数部分至少占3个位宽; 注意:这里的3只代表整数部分至少占3位,舍弃小数点和小数点后面的部分 2.printf("%6.2f".floatNum)...
  • 输出浮点数

    2020-01-14 11:44:26
    读入一个双精度浮点数,分别按输出格式“%f”,“%f”保留5位小数,“%e”和“%g”的形式输出这个整数,每次在单独一行上输出。 【输入】 一个双精度浮点数。 【输出】 第一行是按“%f”输出的双精度浮点数; 第二行...
  • 单精度浮点数,双精度浮点数,浮点数是属于有理数中某特定子集的数的数字表示,在计算机中用以近似表示任意某个实数。
  • 判断浮点数是否为整数浮点数还是小数浮点数 我们一般可以通过type(x)函数直接获取x的数据类型,或者通过isinstance(x, datatype)来判断x是否为datatype类型。但是,有时候,我们需要将如20.0这样小数位无值、类似于...
  • 浮点数 1.默认是double。 2.浮点数存在舍入误差,很多数字不能精确表示。如果需要进行不产生舍入误差的精确数字计算,需要使用BigDecimal类。 3.最好避免比较中使用浮点数。 类型 占用存储空间 表述范围 ...
  • 在C语言中,单精度浮点数(float)和双精度浮点数(double)类型都是用来储存实数的,双精度是用记忆较多,有效数字较多,数值范围较大。
  • 浮点数总结

    千次阅读 2018-08-26 10:19:18
    浮点数在内存中的存储  根据IEEE standard 754,float用4个字节存储,double用8个字节存储。float 1个bit用来存储浮点数的符号,8个bit用来存储浮点数的指数,23个bit用来存储浮点数的尾数。对于double 1个bit用来...
  • IEEE754标准浮点数转换

    万次阅读 多人点赞 2018-08-02 16:13:13
    IEEE754标准是一种浮点数表示标准,一般分为单、双精度两种,单精度是32位的二进制数,双精度是64位的二进制数,一个浮点数的组成分为三个部分 ①第1位是数符s,s=1表示负数,s=0表示正数。 ②第2-9位为阶码E, (双...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 65,370
精华内容 26,148
关键字:

浮点数