精华内容
下载资源
问答
  • 浮点数二进制表示

    千次阅读 2018-07-29 20:59:42
    上面这条命令,声明了一个整数变量,类型为int,值为9(二进制写法为1001)。普通的32位计算机,用4个字节表示int变量,所以9就被保存为00000000 00000000 00000000 00001001,写成16进制就是0x00000009。 那么,...

    在讨论浮点数之前,先看一下整数在计算机内部是怎样表示的。

      int num=9;

    上面这条命令,声明了一个整数变量,类型为int,值为9(二进制写法为1001)。普通的32位计算机,用4个字节表示int变量,所以9就被保存为00000000 00000000 00000000 00001001,写成16进制就是0x00000009。

    那么,我们的问题就简化成:为什么0x00000009还原成浮点数,就成了0.000000?

    下面一步一步的揭晓答案。

    先来看一个公式,计算浮点数的公式:

    根据国际标准IEEE 754,任意一个二进制浮点数V可以表示成下面的形式:

      

      (1)(-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。

      (2)M表示有效数字,大于等于1,小于2。

      (3)2^E表示指数位。

    举例来说,十进制的5.0,写成二进制是101.0,相当于1.01×2^2。那么,按照上面V的格式,可以得出s=0,M=1.01,E=2。

    十进制的-5.0,写成二进制是-101.0,相当于-1.01×2^2。那么,s=1,M=1.01,E=2。

    IEEE 754规定,对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。

    对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。

     

    IEEE 754对有效数字M和指数E,还有一些特别规定。

    前面说过,1≤M<2,也就是说,M可以写成1.xxxxxx的形式,其中xxxxxx表示小数部分。IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。

    至于指数E,情况就比较复杂。

    首先,E为一个无符号整数(unsigned int)。这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,E的真实值必须再减去一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。

    比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001。

    然后,指数E还可以再分成三种情况:

    (1)E不全为0或不全为1。这时,浮点数就采用上面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。

    (2)E全为0。这时,浮点数的指数E等于1-127(或者1-1023),有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。

    (3)E全为1。这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);如果有效数字M不全为0,表示这个数不是一个数(NaN)。

     

    下面,让我们回到一开始的问题:为什么0x00000009还原成浮点数,就成了0.000000?

    首先,将0x00000009拆分,得到第一位符号位s=0,后面8位的指数E=00000000,最后23位的有效数字M=000 0000 0000 0000 0000 1001。

    由于指数E全为0,所以符合上一节的第二种情况。因此,浮点数V就写成:

      V=(-1)^0×0.00000000000000000001001×2^(-126)=1.001×2^(-146)

    显然,V是一个很小的接近于0的正数,所以用十进制小数表示就是0.000000。

    展开全文
  • float浮点数二进制表示转换[源代码]

    热门讨论 2011-04-05 20:34:24
    根据IEEE754规定写了个float型数据与二进制数转换的方法
  • 计算机中的浮点数表示是计算机组成原理的基础知识,相比于整型的计算机表示浮点数的计算机表示相对复杂,现将个人学习心得整理如下,以备后用。 一、浮点数表示  计算机中的浮点数表示格式如下: S exp域...

           计算机中的浮点数表示是计算机组成原理的基础知识,相比于整型的计算机表示,浮点数的计算机表示相对复杂,现将个人学习心得整理如下,以备后用。

    一、浮点数的表示

           计算机中的浮点数表示格式如下:

    Sexp域(E)frac域(M)

    表达式为N=(-1)^{S}*M*R^{E}

    其中S为阶符,用于表示正负符号(取0或1),M为尾数,用于表示精度,E为阶码,它指出的是小数点在数据中的位置,决定了浮点数的表示范围,R为基数,可取2,8,16。本文以R=2为例,说明计算机中浮点数的二进制表示。

            C\C++中经常用到两种浮点数:单精度浮点数和双精度浮点数。单精度浮点数: exp域宽度为8bits,frac域宽度为23bits,1位符号位,总共32bits;双精度浮点数:exp域宽度为11bits,frac域宽度为52bits,总共64bits。

    二、浮点数的类型

         浮点数分为3种类型:规格化浮点数、非规格化浮点数、一些特殊值。

     1.规格化浮点数

        满足条件:exp \neq 000...0 且 exp\neq 111...1

        真实的阶码值需要减去一个偏置量(biased): E = Exp - Bias

    •  Exp: exp域所表示的无符号数值
    •  Bias = 2^{e-1}-1, e = exp域的位数,单精度中的e为8,则Bias=2^{8-1}-1=127; 双精度中的e为11,则Bias=1023

       根据公式可知规格化单精度浮点数中Exp\in[1,254],E\in[-126,127],双精度浮点数中Exp\in[1,2046],E\in[-1022,1023]

         frac域的第一位隐含为1,若M=1.xxx...x(二进制表示),则

    •  第一位的“1”可以省去,xxx...x: bits of frac
    •  最小frac: 000...0
    •  最大frac: 111...1 

       举例:Float F = 15213.0

        15213 = 11101101101101_{2} = 1.1101101101101_{2}  X 2^{13},那么 

        尾数M = 1.1101101101101_{2},frac=1.11011011011010000000000_{2} (小数点后补齐到23位,小数点前的1省略,不算在23之中)

        阶码 E = 13(小数点左移了13位) ; Bias = 127 ; Exp = 140 = 10001100_{2}

    Hex    4        6      6      D      B       4      0        0
    Binary0 100 0110 0110 1101 1011 0100 0000 0000
    15213符号0 + 阶码10001100  + 尾数 11011011011010000000000

      2.非规格化浮点数

         满足条件 exp = 000...0

         其他域的取值 E = -Bias + 1 ; M = 0.XXX...X_{2},XXX...X为frac位数(为什么这么取值呢?可这样理解,在规格化数中Exp可取的最小值为1,此时E = 1-Bias; M = 1.XXX...X_{2},那么当我们要表示比这个数更小的浮点数时怎么办呢,只能牺牲精度,将小数点左移变成0.XXX...X_{2}

    举个例子,

    用单精度表示最小的规格化浮点数,

    Exp=1,E=-126,M=1.0,N=1.0*2^{-126}

    二进制表示为0 00000001 00000000000000000000000,

    那么表示最小的非规格化浮点数,

    Exp=0,E=-126,M=1.0*2^{-23},N=2^{-23}*2^{-126}

    二进制表示为0 00000000 00000000000000000000001)

      3.一些特殊值

        满足条件 exp=111...1

        具体示例 exp=111...1,frac=000...0 表示无穷,可用于表示数值的溢出

    三、答疑

    1. 为什么阶码用移码表示?

          答:移码即将补码的符号位取反所得到的码,在计算机中将有符号数的原码、反码、补码的最高位作为符号位,且0表示正数,1表示负数,那么比较时则可能导致错误,因为计算机认为1比0大,而正数的补码与原码相同,负数的补码是反码的末尾加1,正负数分别取移码,正数的符号位变为1,负数的符号位变为0,这时再比较就很简单明了,所以,将阶码用移码表示。

    本文是根据清华大学计算机的浮点数表示视频整理所得,若有错误,多多辅正!

    展开全文
  • 关于字节与位: 一个int占4个字节(byte),一个字节占8位(bit),所以一个int占用4x8=32位。 char类型的范围为什么是-128~127? 有一个整型范围的公式:-2^(n-...char占8位,用二进制表示为 0000 0000 ~ 1111 111...

    先看看整数的二进制表示

    关于字节与位:

    一个int占4个字节(byte),一个字节占8位(bit),所以一个int占用4x8=32位。

    char类型的范围为什么是-128~127?

    有一个整型范围的公式:-2^(n-1)~2^(n-1)-1 (n为整型的内存占用位数)。

    对于char类型,占一个字节,n=8,代入得:-128~127。

    char占8位,用二进制表示为 0000 0000 ~ 1111 1111,1111 1111最大即为十进制255,所以 unsigned char 的范围为0~ 255。

    但是对于有符号整数,二进制的最高位表示正负,不表示数值,最高位为 0 时表示正数,为 1 时表示负数,这样一来,能表示数值的就剩下( n-1 )位了,比如 char a = -1;   那么二进制表示就为 1 0000001,1 表示为 0 0000001,所以 signed char 型除去符号位剩下的 7 位最大为 1111 111 = 127,再把符号加上,0 1111111 = 127,1 1111111 = -127,范围应该为 -127~127。

    但会有问题出现:

    先看1+1=?

      0000 0001
    + 0000 0001
    ———————————
      0000 0010 ……………… 2 运算正确

    再看1-1=?,由于计算机只会加法不会减法,它会转化为1+(-1)=?

      0000 0001
    + 1000 0001
    ___________
      1000 0010 …………… -2 运算错误

    1-1 = -2?  这显然是不对了,所以为了避免减法运算错误,计算机大神们发明出了反码,直接用最高位表示符号位的叫做原码, 上面提到的二进制都是原码形式,反码是原码除最高位其余位取反,规定:正数的反码是其本身,负数的反码是原码除了符号位,其余为都取反。现在再用反码来计算 1+(-1) :

      0000 0001
    + 1111 1110
    ————————————
      1111 1111 ………… 再转化为原码就是 1000 0000 = -0  

    虽然反码解决了相减的问题,却又带来一个问题:-0 ,既然 0000 0000 表示 0,那么就没有 -0 的必要, 出现 +0 = -0 = 0 ,一个 0 就够了,为了避免两个 0 的问题,计算机大师们又发明了【补码】,补码规定: 正数的补码是其本身,负数的补码为其反码加一 ,所以,负数转化为补码需两个步骤:第一,先转化为反码;第二, 把反码加一。


    正数的反码、补码都是本身;负数的码=除符号位都取、负数的码=反码+1

    记:反码与补码是针对负数而发明的,所以正数反码、补码就是本身。对负数:“反”码,即(除符号位)都取“反”;“补”码,即“补”一位(+1)。


    这样1+(-1) :

      0000 0001
    + 1111 1111
    ___________
    1 0000 0000 ……………………  由于 char 为 8 位,最高位 1 被丢弃结果为 0 ,运算正确。

    -0 :原码 1000 0000 的补码为 1 0000 0000 ,由于 char 是 八位 ,所以取低八位 0000 0000。   
    +0 :原码 0000 0000 ,补码为也为 0000 0000 ,虽然补码 0 都是相同的,但是有两个 0 ,既然有两个 0 ,况且 0 既不是正数,也不是负数, 用原码为 0000 0000 表示就行了。

    这样一来,有符号的 char,原码都用来表示 -127~127 之间的数了,唯独剩下原码 1000 0000 没有用。1000 0000作为负数,反码:1111 1111,补码为:1111 1111 + 0000 0001 = 1 0000 0000(最高位1表示负数,后面8位,2^7=128,则表示-128)

    -128 的原码和 -0(1000 0000) 的原码相同吗?答:是不同的。但是在 char 型中,是可以用 1000 0000 表示 -128 的,关键在于char 是 8 位,它把 -128 的最高位符号位 1 丢弃了,截断后 -128 的原码为 1000 0000 和 -0 的原码相同,也就是说 1000 0000  和 -128 丢弃最高位后余下的 8 位相同,所以才可以用 -0 表示 -128,这样,当初剩余的 -0(1000 0000),被拿来表示截断后的 -128,因为即使截断后的 -128 和 char 型范围的其他 (-127~127) 运算也不会影响结果, 所以才敢这么表示 -128。

    比如 -128+(-1) :

      1000 0000   ------------------ 丢弃最高位的-128
    + 1111 1111   ------------------ -1
    ___________
     10111 1111   ------------------ 用"%c"未打印任何字符,用"%d"打印-129,不过没关系,溢出char型了,当然不能表示了。

    比如 -128+127:

      1000 0000
    + 0111 1111
    ———————————
      1111 1111 ------- -1 结果正确, 所以,这就是为什么能用1000 0000表示-128的原因。
    
    注:1111 1111 ->取原码(逆操作:减一再取反码)=>1000 0001 = -1

    对于浮点数二进制是怎么表示的呢?

    根据国际标准IEEE 754,任意一个二进制浮点数V可以表示成下面的形式:

      V = (-1)^s×M×2^E
      (1)(-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。
      (2)M表示有效数字,大于等于1,小于2。
      (3)2^E表示指数位(E是二进制数)。
      举例来说,十进制的5.0,写成二进制是101.0,相当于1.01×2^2。那么,按照上面V的格式,可以得出s=0,M=1.01,E=2。
      十进制的-5.0,写成二进制是-101.0,相当于-1.01×2^2。那么,s=1,M=1.01,E=2。
      IEEE 754规定,对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。
      对于64位的浮点数,最高的1位是符号位s,接着的11位是指数E,剩下的52位为有效数字M。
      IEEE 754对有效数字M和指数E,还有一些特别规定。
      前面说过,1≤M<2,也就是说,M可以写成1.xxxxxx的形式,其中xxxxxx表示小数部分。IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。
      至于指数E,情况就比较复杂:
      ➀E为一个无符号整数(unsigned int)。IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,8位的E这个中间数是127;对于11位的E,这个中间1023。这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的取值范围为0~2047。

           ➁E为一个有符号整数(int)。IEEE 754规定,存入内存时E的真实值必须再减去一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。
      比如,2^10的E是10(此时是10进制表示),所以保存成32位浮点数时,必须保存成E=10+127=137,即10001001。
      然后,指数E还可以再分成三种情况:
      (1)E不全为0或不全为1。这时,浮点数就采用上面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。
      (2)E全为0。这时,浮点数的指数E等于1-127(或者1-1023),有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
      (3)E全为1。这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);如果有效数字M不全为0,表示这个数不是一个数(NaN)。
      关于浮点数的表示规则,就到这里。

    如float=9.0的内存中表示:


    下面num和*pFloat在内存中明明是同一个数,为什么浮点数和整数的解读结果会差别这么大?

    #include <stdio.h>
    int main(void) {
    	int n = 9;
    	float f = 9.0;
    	float* fpn = &n;
    	float* pf = &f;
    	printf("sizeN=%zu,sizeF=%zu\n", sizeof n, sizeof f); // #0
    	printf("n=%d -> &n=%p\n", n, &n);
    	printf("f=%f -> &f=%p\n", f, &f);
    	*fpn = 10;
    	*pf = 10.0;
    	printf("*pf=%f -> *fpn=%f\n", *pf, *fpn); // #1
    	printf("*fpn=%f -> *pf=%f", *fpn, *pf); // #2
    	return 0;
    }
    sizeN=4,sizeF=4
    n=9 -> &n=00AFFCCC
    f=9.000000 -> &f=00AFFCC0
    *pf=10.000000 -> *fpn=0
    *fpn=0 -> *pf=0.000000

    ➊为什么#1行打印的*pf正确,而#2行只是调换了个位置*pf打印却为0?

    ➋为什么*fpn总打印为0?

    ➌为什么sizeN==sizeF==4?

    断点调试:

    从疑问➋开始,整体原因是将float*类型赋值为了int*类型,是不匹配的指针类型赋值操作。通过断点调试发现fpn的地址没变为0x001efc3c,但其表示的值为1.261e-44#DEN,相当于fpn指向的地址是1.261e-44#DEN,所以*fpn不是一个有效地址,1.261e-44#DEN#DEN是指非规格化数 (denormalized value), 简单来说就是float/double 数字太小了,近乎0的意思。

    对于疑问➌,因为fpn虽然是float *,但被赋值为int大小空间的地址,也就是float类型大小只能存储在int类型大小空间里,所以sizeof n == sizeof f。

    对于疑问➊,把#1和#2行改为如下:

    printf("*pf=%f -> *fpn=%f\n",*pf, *fpn); // #1
    printf("*fpn=%f -> *pf=%f", *fpn, *pf); // #2
    打印输出:
    *pf=10.000000 -> *fpn=10.000000
    *fpn=10.000000 -> *pf=10.000000

    因为fpn这个指针变量声明为float类型,它存储的地址是无效的。其实无论怎样,都应该类型正确的匹配!

    从上面可以看到,原来的代码直接就报警告“an integer is required in call to 'printf' Actual type:'float'”了。将所有%d都改为%f,就不报警告了,并且输出是正确的值。 

    printf("*fpn=%d -> *pf=%f", *fpn, *pf);//#2 输出:0 -> 0.000000
                  ⇓
    printf("*fpn=%f -> *pf=%f", *fpn, *pf);//#2 输出:10.000000 -> 10.000000

    第一行有警告:C6273:Non-integer passed as_Param_(2) when an integer is required in call to 'printf' Actual type: 'float': if a pointer value is being passed,%p should be used.

    第二行,仅是*fpn=%d变为%f,连后面打印的值都正确了,也是神奇,在此留个疑问。

    总之,由于fpn是一个指针float类型但只占4个字节存储内容的指针,既然是float类型指针,当然应该用%f打印值了!

    看个更简单的例子就更加清晰明白了:

    #include <stdio.h>
    int main(void) {
        int i = 0x12345678;
        float f = 0x1efc3c;
        double d = 1.79E+38;
        printf("===Wrong===\n");
        printf("%d\n", f);
        printf("%f\n", i);
        printf("%d\n", d);
        printf("===Right===\n");
        printf("%f\n", f);
        printf("%lf\n", d);
        return 0;
    }
    
    输出:
    ===Wrong===
    0
    0.000000
    -1408126465
    ===Right===
    2030652.000000
    179000000000000018071044723816240513024.000000

    因为int与float/double类型在内存中存储模式是不一样的!

    int32的整数0x12345678在内存中对应二进制表示为:

    【0】[0010 0100]{011 0100 0101 0110 0111 1000}
    第一位符号位0,接下来8位是指数位: 0010 0100, 换算成十进制是: 36。不过浮点数的格式规定,这个数还要减去127才是真正的指数,36 -127 = -91。最后23位是底数位。不过浮点数的格式规定,这个数前面要加上【1.】才是真正的底数,所以底数是1.011 0100 0101 0110 0111 1000。这个数换算成十进制大约是1.40625。最后整个浮点数的值是 1.40625 * 2 ^ -91,计算结果是5.6797985e-28,也就是零点零零零(一共28个零)五六七九七九八五。printf后面的%f只保留6个有效数字,所以就变成0了。

    下面来讲一下  float a=7.5f ; printf("%d",a)输出为0的情况:

    如果用printf("%d",(float)a),输出什么,输出的是0,这个只是将a的float类型还转成float类型,还是自动转成doube类型,传给printf函数。
            为什么float非要转成double类型呢,因为printf格式控制浮点型输出只有%f,所以统一按doube类型输出,不像整型有32位的%d或%ld,64位的有%lld,这就将32位整型和64位整型用不同的格式控制分开了,而%f则没有,所以printf输出的浮点数其实是统一遍历了64位内存,如果float传入printf没有进行转换,那么printf输出高32位数据将不可预知,printf输出结果也就不正确了,因此传入printf的浮点数都会被编译器隐含转成double类型。
            %d只输出低32位的数据,并将这些32位二进制以十进制数输出,编译器首先将 7.5从float类型转换为double类型,7.5在内存中的存放方式是0x40f00000,转换成double类型在内存中的数据就是这个0x401e000000000000,这个内存数据可以很明显看出低32位全是0,而%d则只能截取到低32位,所以这个以%d输出7.5的数值当然是 0了。如大家不相信可以用%lld 输出看看,这个%lld就很读到低64位数据,读出的结果就是0x401e000000000000,在屏幕上看到一个很大的十进制数。
            如果我一定要输出7.5在内存中的存放方法怎么办呢?
            可以用printf("%d",*(int *)&a);这里做了一下处理,不是直接把a传进来,把a所在地址里的内容处理了一下,不管a是什么类型,只对地址进行操作,利用(int *)&a,将a所在地址中的内容0x40f00000直接当成 int 类型传给printf,int 的类型数据不会再转成double类型了,所以输出正常,这个只是针对浮点型数据只占低32位,如果输出64位还得用%lld格式控制输出。
            如果用printf("%d",(int)a),输出行不行,这个强制类型转换只针对a的数据类型进行转换,7.5转换 int 类型是7,而上面的*(int *)&a,是对内存中的实际存储数据进行操作,蔽开数据类型这一层面,只将这个数据0x40f00000直接转成int类型输出。而(int)a,要先看a的类型,C语言会根据所要数据类型,对内存存储的数据进行改变,以便可以用int类型正确解析内存数据。

    浮点数在计算机内部的表示方法

    现代计算机中,一般都以IEEE 754标准存储浮点数,这个标准的在内存中存储的形式为:

    对于不同长度的浮点数,阶码与小数位分配的数量不一样,如下:

    对于32位的单精度浮点数,数符分配是1位,阶码分配了8位,尾数分配了是23位。

    根据这个标准,我们来尝试把一个十进制的浮点数转换为IEEE 754标准表示。

    例如:178.125

    ➀先把浮点数分为整数部分和小数部分转换成2进制。
        整数部分2进制表示:10110010
        小数部分2进制表示:001(0×2^-1+0×2^-2+1×2^-3=0.125)
        合起来即是:10110010.001
        转换成二进制的浮点数,即把小数点移动到整数位只有1,即为:1.0110010001 * 2^111,111是二进制,由于左移了7即二进制111
    ➁把浮点数转换二进制后,这里基本已经可以得出对应3部分的值了。
        数符:由于浮点数是正数,故为0(负数为1)
        阶码 : 阶码的计算公式:阶数 + 偏移量,  阶码是需要作移码运算,在转换出来的二进制数里,阶数是111(十进制为7),对于单精度的浮点数,偏移值为01111111(127)[偏移量的计算是:2^(n-1)-1, n为阶码的位数,即为8,因此偏移值是127],即:111+01111111 = 10000110
        尾数:小数点后面的数,即0110010001
        最终根据位置填到对位的位置上:

    小数点前面的1去哪里了?由于尾数部分是规格化表示的,最高位总是“1”,所以这是直接隐藏掉,同时也节省了1个位出来存储小数,提高精度。


           ➊为什么9还原成浮点数,就成了0.000000?
      首先,9对应二进制为0000 0000 0000 0000 0000 0000 0000 1001,和上图对比,符号位s=0,E=0000 0000,最后23位的有效数字M=000 0000 0000 0000 0000 1001。
      由于指数E全为0,所以符合上面的第(2)种情况。因此,浮点数V就写成:
      V=(-1)^0×0.00000000000000000001001×2^(-126)=1.001×2^(-146)
      显然,V是一个很小的接近于0的正数,所以用十进制小数表示就是0.000000。


           ➋浮点数9.0,如何用二进制表示?还原成十进制又是多少?
      首先,浮点数9.0等于二进制的1001.0,即1.001×2^11(11为二进制)。
      那么,第一位的符号位s=0,有效数字M等于001后面再加20个0,凑满23位,指数E等于3+127=130,即10000010。
      所以,写成二进制形式,应该是s+E+M,即0 10000010 001 0000 0000 0000 0000 0000。这个32位的二进制数,还原成十进制,正是1091567616。

    展开全文
  • float浮点数二进制表示转换

    热门讨论 2011-04-05 20:29:45
    根据IEEE754规定写了个float型数据与二进制数转换的方法
  • floatbin浮点数二进制/16进制表示转换工具(附带源代码) 很实用,代码也值得参考
  • 浮点数二进制表示

    千次阅读 2017-01-11 10:37:00
    下面以单精度浮点数(float)为例描述下浮点数二进制表示方法。 float占4个字节(32bit),每一bit的作用域如下: sign占1bit,表示正负号(0为正,1为负)。 exponent占8bit,表示指数。(127表示指数为0,如

    我们期望浮点数也可以像定点数(整数)一样在计算机中以二进制方式存储,但是计算机不能识别小数点,于是一种新的存储方式产生了,即IEEE754浮点表示。

    下面以单精度浮点数(float)为例描述下浮点数二进制表示方法。
    float占4个字节(32bit),每一bit的作用域如下:

    sign占1bit,表示正负号(0为正,1为负)。
    exponent占8bit,表示指数。(127表示指数为0,如果指数为正,则exponent表示为127+E,如果指数为负,则exponent表示为127-E(指数位))
    fraction占23bit,表示小数有效位。(这里会减去整数位1(取值时加上1),只填充小数位部分,没有填充满的位补0)

    综上,一个单精度浮点数所代表的数值为:


    补充:
    当exponent全为0时,浮点数的指数E等于1-127,有效数字fraction不再加上第一位的1,而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
    当exponent全为1时,如果小数位fraction全为0,表示±无穷大(正负取决于符号位sign);如果小数位fraction不全为0,表示这个数不是一个数(NaN)。

    举例(以-12.5为例):
    1. 先将-12.5转化为带小数点的二进制:-1100.1
    2. 将小数点移到第一个1的后面-1.1001*2^3
    3. 转化为IEEE754表示法:
       符号位:1
       指数位:127(偏移量/表示0)+3 = 130,即二进制10000010
       小数位:1001(去除了整数部分),余下的位补0,即10010000000000000000000
    4. 拼凑起来:1 10000010 10010000000000000000000

    float的表示范围:
    1.99999...9 * 2^(255-127) 约为 2*2^128 = 3.4*10^38
    加上正负号,即为单精度浮点数范围:-3.4*10^38 ……3.4*10^38
    由此可见:单精度浮点数表示的数值最大为2*2^128,远大于整数(int)的2*2^32;但是单精度浮点数的有效小数位只有23位(<32),精度有限。

    双精度浮点数(double)表示如下:

    展开全文
  • 之前写过一篇“谈谈JavaScript的算数运算、浮点数二进制表示舍入误差及比较、类型转换和变量声明提前问题”,当时主要是阐述浮点数运算产生的舍入误差及js类型转换和变量申明提前问题,所以只是略微提及了js中浮点数...
  • 小数部分0.5, 二进制是.1,先把他们连起来,从第一个1数起取24位(后面补0):1100.10000000000000000000这部分是有效数字。(把小数点前后两部分连起来再取掉头前的1,就是尾数)2. 把小数点移到第一个1的后面,需要...
  • 补码二、浮点数二进制表示 前言 对于该代码 public class hello { public static void main(String[] args) { int a = -17; System.out.println("二进制输出"+Integer.toBinaryString(a)); int b = 17; ...
  • 浮点数二进制表示 符号位、尾数和指数(以64位浮点数为例) 0、规约数和非规约数 无穷大和空值NaN 二进制的科学计数法 浮点数在电脑中用二进制储存,约定以二进制的科学计数法来进行表示一个浮点数,类比十...
  • 浮点数二进制表示

    千次阅读 2017-12-23 10:38:18
    目前C/C++ 编译器标准都遵照IEEE 制定的浮点数表示法来进行float,double 运算。这种结构是一种科学计数法,用符号、指数和尾数来表示,底数定为2—— 即把一个浮点数表示为尾数乘以2 的指数次方再添上符号。
  • 浮点数的储存和整形的储存方法是截然不同的,整形是将数据的二进制编码补码放入内存中,而浮点数的储存是一种全新的规则。 浮点数存储的例子: int main() { int n = 9; float *pFloat = (float *)&...
  • IEEE 754 与浮点数二进制表示​ponder.work本文同步发布个人博客在计算机科学中,浮点(英语:floating point,缩写为FP)是一种对于实数的近似值数值表现法, 类似于十进制的科学计数法. 科学记数法在科学记数法中...
  • 浮点数二进制表示方法

    万次阅读 2018-09-04 11:09:17
    浮点数二进制表示 Double型,64位 例一: 已知:double类型38414.4,求:其对应的二进制表示。 分析:double类型共计64位,折合8字节。 由最高到最低位分别是第63、62、61、……、0位: 最高位63位是符号位,...
  • 虽然以前也学过浮点数表示原理,大致的原理还是清楚的,但是使用 C 语言的来进性验证还没有尝试过,下面是验证的过程思路知道浮点数,是按照 32 位在内存中保存,其中第一位表示符号,后 8 位表示指数,最后 23 位...
  • 浮点数二进制与十进制之间的转换 在使用遗传算法的时候,需要对数据进制二进制编码,所以改的这个浮点数不同进制之间转换的一个代码 直接上代码 #二进制转化为十进制浮点数 def todecimal(n): ''' 把一个带小数的...
  • 为什么要注意这三点: 1、首先是项目中用到的进制转换,常用的int ord hex 以及编写的转换函数,作为记录 ... 二进制,十六机制转十进制比较容易,直接int(‘7a’,16)就可以了,但是注意这里是单字节,也就是...
  • 详解浮点数二进制表示

    千次阅读 2017-09-19 10:37:33
    1.十进制转二进制方法  十进制数转换为二进制数 十进制数转换为二进制数时,由于整数和小数的转换方法不同,所以先将十进制数的整数部分和小数部分分别转换后,再加以合并。  1.1十进制整数转换为二进制整数 ...
  • 浮点数二进制表示 前几天,我在读一本C语言教材,有一道例题:  #include <stdio.h>  void main(void){  int num=9; /* num是整型变量,设为9 */  floa...
  • C语言浮点数二进制表示
  • 浮点数二进制表示(IEEE 754标准)

    千次阅读 2018-12-03 15:18:07
    浮点数是我们在程序里常用的数据类型,它在内存中到底是怎么样的形式存在,是我了解之前是觉得好神奇,以此记录,作为学习笔记。 现代计算机中,一般都以IEEE 754标准存储浮点数,这个标准的在内存中存储的形式为:...
  • 原文参考:... 小数部分0.5, 二进制是.1,先把他们连起来,从第一个1数起取24位(后面补0):1100.10000000000000000000这部分是有效数字。(把小数点前后两部分连起来再取掉头前的1,就是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 123,428
精华内容 49,371
关键字:

浮点数的二进制表示

友情链接: subtitle_test_b01.zip