《競賽演算法入門經典》 習題3-12 浮點數
阿新 • • 發佈:2018-12-15
《競賽演算法入門經典》 習題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的位置。
(きょうは八百米を走った)