float和double浮点数的运算过程

版权声明:原创。欢迎转载,转载请注明来源,谢谢。 https://blog.csdn.net/qq_41910280/article/details/82528221

float和double浮点数的运算过程

本人邮箱:[email protected] [email protected]
[email protected] 欢迎交流讨论。
欢迎转载,转载请注明网址:https://blog.csdn.net/qq_41910280

目录

简介:本文以float为例,演示了浮点数在计算机底层的存储方式、浮点数10进制与2进制间的相互转换以及浮点数加减运算全过程。

1. 浮点数在计算机底层的存储方式

  不论是float还是double在存储方式上都是遵从IEEE 754的规范。根据国际标准IEEE 754,任意一个二进制浮点数V可以表示成下面的形式:
IEEE 754浮点数计算公式
  (1)S(Sign)表示符号位,当S=0,V为正数;当S=1,V为负数。

  (2)M(Mantissa)表示尾数(2进制),大于等于1,小于2。

  (3)E(Exponent)表示指数位。
  (不理解的先看下科学计数法
  
  其中单精度浮点数float遵从IEEE R32.24,存储方式如下图所示:
  float存储方式
  双精度浮点数double遵从R64.53,存储方式如下图所示:
  double存储方式
  
  
  IEEE 754规定,在计算机内部保存M时,因为M范围是[1,2),默认这个数的第一位总是1,因此可以被舍去,只保存后面的小数部分。所以float类型23位的M可以表示24位二进制数,double类型52位的M可以表示53位二进制数。
  IEEE754规定E为一个无符号整数(unsigned int)。这意味着,float类型E的取值范围为0~255;double类型E的取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的。所以IEEE 754规定,计算机中存储的E为实际值加上中位数,这个中位数对于float类型8位E是127,对于double类型11位的E这个值是1023。即,在float中,E用125表示-2,用127表示0,用128表示1。
  
  

2. 十进制数与二进制浮点数之间的转换

  
  以1.0F、0.42F为例。
  1.0F(10进制)=1.0(2进制)×2^0。S=0(正数);E=0,在计算机中加上127为127;M=1.0,在计算机中为23位0。所以转换为内存或硬盘中的二进制数为
  0(S)011 1111 1(E)000 0000 0000 0000 0000 0000(M)。
  
  0.42F要稍微复杂一点,小数转换为二进制要不断乘以2,乘积大于1时,余1,小于1时,余0,余数排列方向与整数转二进制相反,过程就不演算了。也可以直接使用工具 ——》 链接:IEEE 754 单精度浮点数转换
  0.42F(10进制)=1.10101110000101000111101(2进制)×2^(-2),float类型M只保留24位有效数字,多余被计算机省略。S=0(正数);E=-2,在计算机中加上127为125;M=1.10101110000101000111101,在计算机中省去1,为10101110000101000111101。所以转换为内存或硬盘中的二进制数为
  0(S)011 1110 1(E)101 0111 0000 1010 0011 1101(M)。等于十进制的0.4199999868869781494140625,产生了精度损失。(这里留一个问题给大神们:直接打印0.42F结果为0.42,似乎没有精度损失?!——>见本文评论
  
  

3. 加减运算

  
  加减运算,以1.0F-0.42F为例。
  计算过程
  1.0F和0.42F都是遵循IEEE 754规范,以二进制形式储存在计算机中,分别为0(S)011 1111 1(E)000 0000 0000 0000 0000 0000(M)、0(S)011 1110 1(E)101 0111 0000 1010 0011 1101(M)。
  在加减运算时,第一步:指数低的数向指数高的数转换,这里0.42F的E=011 1110 1,1.0F的E=011 1111 1,所以0.42F发生转换,结果为0(S)011 1111 1(E)011 0101 1100 0010 1000 1111(M)。这里的M只有23位(有效位数22),或者说最高的第24位为0。而且移位过程中省略了移位多出来的位数01,发生第二次精度损失。
  
  第二步:结果的M值进行加减运算,即1000 0000 0000 0000 0000 0000(M)-0011 0101 1100 0010 1000 1111(M),结果为100 1010 0011 1101 0111 0001(M)。这里的M同样也只有23位(有效位数23),或者说最高的第24位为0。结果见图。
  
  第三步:将第二步的结果转换为IEEE 754标准(详见), 结果为0(S) 011 1111 0(E) 001 0100 0111 1010 1110 0010(M),转换为10进制为0.58000004291534423828125,控制台打印结果为

0.58000004

  这是第三次精度损失。
  
  额外补充:第二步还有一种可能,就是计算过程保留移位的小数,这样计算精度更高,不过计算效率会降低。
  如果采用这种方式计算,0.42F在计算时会移位为(S)011 1111 1(E)011 0101 1100 0010 1000 1111 11(M多保留了2位,M=11 0101 1100 0010 1000 1111 11,有效位数24位),运算结果为0(S)011 1111 0(E)001 0100 0111 1010 1110 0001(M),换为10进制为0.579999983310699462890625。
  经过上面的分析,第一种计算方式的第二次精度损失发生在移位过程中省略的两位有效数字;而与第一种计算方式不同,第二种计算方式,第二次精度损失发生在加减后转换为IEEE 754标准的时候。
  跟控制台输出的结果对比,我初步判断,计算机采用的是第一种计算方式进行的运算。

  
  

扫描二维码关注公众号,回复: 3185165 查看本文章

4. 总结

  
  
  A、演示了浮点数在计算机内部的存储与运算;
  
  B、在同类型两个浮点数进行加减运算并打印的过程中,可能会产生0 - 4次精度损失。分别为两个十进制数转换为二进制存储的过程、低位数向高位数移位的过程、结果转换为十进制数打印的时候。
  
  C、浮点数运算,指数低的数向指数高的数移位时没有保留多出来的位数。
  

  

猜你喜欢

转载自blog.csdn.net/qq_41910280/article/details/82528221
今日推荐