【Class 学习笔记】 浮点数的储存,运算

一、前言

       Mr. Stan讲这个知识点过去了一个星期吧,今天才把认真的回忆了一边。记录

       Tiger同志给出了一段小程序,Tiger讲课真的很厉害,就是有点快......      

View Code
#include "stdio.h"

void ByteBinOutput(char a)
{
int i;
for(i=7;i>=0;i--)
{
if((1 << i) & a)
printf("%c", '1');
else
printf("%c", '0');
}
}

void Output32Bit(char *string)
{
printf("\n");
ByteBinOutput(*(string+3));
printf("-");
ByteBinOutput(*(string+2));
printf("-");
ByteBinOutput(*(string+1));
printf("_");
ByteBinOutput(*(string+0));
printf("\n");
}

void Output64Bit(char *string)
{

printf("\n");
ByteBinOutput(*(string+7));
printf("-");
ByteBinOutput(*(string+6));
printf("-");
ByteBinOutput(*(string+5));
printf("_");
ByteBinOutput(*(string+4));
printf("_");
ByteBinOutput(*(string+3));
printf("-");
ByteBinOutput(*(string+2));
printf("-");
ByteBinOutput(*(string+1));
printf("_");
ByteBinOutput(*(string+0));
printf("\n");
}


int main()
{

double testb=3.3; /*(float)5/128;*/
double testc=1.1; /*(float)5/128;*/
double testa;

float a,b,c; int d;
b=3.3; c=1.1;
printf("\n--------float b=3.3-------");
printf("\n--------float c=1.1-------");
Output32Bit(&testb);
Output32Bit(&testc);
a=b/c;
d=b/c;
printf("a=%f d=%d\n",a,d);
if(3.0==a)
printf("a==3.0\n");


printf("\n--------double testb=3.3-------");
printf("\n--------double testc=1.1-------");
Output64Bit(&testb);
Output64Bit(&testc);
testa=testb/testc;
d=testb/testc;
printf("testa=%lf d=%d\n",testa,d);
if(3.0!=testa)
printf("testa!=3.0\n");




return 1;

}

       输出:

View Code

      为什么?

二、资源

      1、浮点数的二进制表示,基础 IEEE标准表示

           http://www.ruanyifeng.com/blog/2010/06/ieee_floating-point_representation.html

      2、浮点数的二进制表示例子,很详细的例子,最重要的是,例子给的结果没错!!!

           http://www.cnblogs.com/liu-wei/archive/2011/07/05/2098354.html

      3、C语言printf %f 的原理

           http://www.cnblogs.com/Xiao_bird/archive/2010/03/26/1696908.html

      4、还有一篇,初步入门还可以,不要看例子,例子错误太多了....

          http://www.cnblogs.com/jillzhang/archive/2007/06/24/793901.html#2225730

三、思考

        1、浮点数3.3的二进制表示?

            按照IEEE标准

            3=011;0.3=0100110011001..... (所谓循环)

            3.3什么尾数,什么阶数E=e+127,什么的,忘了就看资料去。

           自己算的和程序给的结果对比下:

--------float b=3.3-------
01100110-01100110-01100110_01100110

--------double testb=3.3-------
01000000-00001010-01100110_01100110_01100110-01100110-01100110_01100110

       2、为什么a==3.0,而换成double进行运算后 testa!=3.0?

            由于d=2,可以确定,整数部分为2

            首先两点:

            a、float 计算机中储存为32位(1+8+23);double 计算机中储存为64位(1+11+52)

            b、数值在进行运算的时候全部为扩展为80位进行运算,储存的时候按规定的位数进行截断

           那么,double 的精度明显要高于float

           第一种情况下,float a,b,c

            b/c 运算结果假设为2.999999999....这样的80位

            a=b/c,进行储存,80位截断为32位,这里应该是有进位什么的,float里面存成了3.000000

            所以 3.0==a  

           第二种情况下,double testa,testb,testc

             testb/testc运算结果也假设为2.999999999..这样的80位

             testa=testb/testc,进行储存,80位截断为64位,这里可能截断的地方么有产生进位,testa里面存为了2.99999...这样的二进制64位        

             所以 3.0!=testa  

             至于testa的输出结果为3.000000,我没有看官方的printf的格式解释,猜想%f读取32位,也在32位的那个地方截断,所以效果和float一样了。 

       3、 十进制转二进制

            哈哈,其实发现这段代码最高兴的就是转二进制的那段了,给了我很大的启发。

            开始自己想写一个转换的函数来着,思路一直局限在/2,*2什么的,还想在小数点那里怎么分呢。看了这段程序就恍然大悟了。

            计算机内存里面全部都是0和1,为什么还要你自己去算呢,取出来就好了。

            思想就是:每次读一个字节,循环移位读'0','1'

                                                      

原文地址:https://www.cnblogs.com/hundan/p/2221882.html