《竞赛算法入门经典》 习题3-12 浮点数

《竞赛算法入门经典》 习题3-12 浮点数

在这里插入图片描述
(嗯……我不懂)(根据https://blog.csdn.net/ShannonNansen/article/details/42059693的内容)
对于任意一个二进制数N,可用N=S×2^P表示,其中S为尾数,P为阶码,2为阶码的底,P、S都用二进制数表示,S表示N的全部有效数字,P指明小数点的位置。
当S为纯小数时,此时定点数只能表示小数,所能表示的N范围是(1-2^-n) ≥N≥-(1-2^-n)。
根据题目,小数点后第一位必须为1,位数自带一个1,这个1不被存储的,所以对于某个a位二进制数的尾数,它的十进制尾数值m=1-2^(-a-1)。
尾数是指一个数目中末位的数码
(浮点)数值 =尾数(mantissa)× 底数 ^ 指数(exponent),(附加正负号)(应当满足 尾数 < 底数 )。
所以输入的A×10^B =M×2^E,
两边取对数,log10(M)+E*log10(2)=log10(A)+B。令左边为t,则d=t-log10(A),因为1<=A<10,所以log10(A)<1,因为B为指数,为正,所以B=t/1(向下取整),所以A=10^(t-B)。

#include<stdio.h>
#include<math.h>
#include<string.h>
void find(double m,long long e);
double M[11][33];
long long E[11][33];
int main()
{
	int i,j;
	double m,t;
	long long e;
	char str[22];
	for(i=0;i<=9;i++)//根据上述公式打表,每一个对应位的尾数和指数分别存储
		for(j=1;j<=30;j++)
		{
			e=(1<<j)-1;		//底数是2,所以<<来乘以2,乘以2…… 
			m=1-1.0/(1<<(i+1)); //也是上面说的 
			t=log10(m)+e*log10(2);
			E[i][j]=t/1;
			M[i][j]=pow(10,t-E[i][j]);
		}
	while(~scanf("%s",str)&&strcmp(str,"0e0"))  //如果str=0e0,返回0,不执行 
	{
		*(strchr(str,'e'))=' ';		//(strchr(s,c)可以在字符串s中查找首次出现c的位置)可以将字符串中的e替换成空格
		sscanf(str,"%lf %lld",&m,&e);	//(sscanf 读取格式化的字符串中的数据。)运用sscanf巧妙分割尾数和指数
		find(m,e);
	}
	return 0;
}
void find(double m,long long e)	//一开始不知道为什么要写一个函数,原来是为了方便找到值后,用return结束。
{
			int i,j;
	    for(i=0;i<=9;i++)
	    	for(j=1;j<=30;j++)
			    if(e==E[i][j]&&fabs(m-M[i][j])<1e-5)	//当指数等于表中所给并且尾数差值绝对值小于误差时即匹配,输出答案,跳出函数
		    	{
			    	printf("%d %d\n",i,j);
			    	return;
			    }
} 

sscanf的用法如:
char buf[512] = ;
sscanf(“123456 “, “%s”, buf);
printf(”%s\n”, buf);
结果为:123456

strchr:
char *strchr(const char *s,char c),可以查找字符串s中首次出现字符c的位置。
(きょうは八百米を走った)

猜你喜欢

转载自blog.csdn.net/weixin_43326028/article/details/83717874