【Class 学习笔记】 浮点数的储存,运算
一、前言
Mr. Stan讲这个知识点过去了一个星期吧,今天才把认真的回忆了一边。记录
Tiger同志给出了一段小程序,Tiger讲课真的很厉害,就是有点快......
#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;
}
输出:
为什么?
二、资源
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'