1. 程式人生 > >《競賽演算法入門經典》 習題3-12 浮點數

《競賽演算法入門經典》 習題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的位置。
(きょうは八百米を走った)