UVa11809 - Floating-Point Numbers

題目

UVa11809

解讀

其實(shí)這題是一題數(shù)學(xué)題,核心是電腦儲存浮點(diǎn)數(shù)的方式。
從我們的科學(xué)記數(shù)法說起。對于任意一個實(shí)數(shù)(十進(jìn)制),都可以用A*10^B 來表示。但是電腦只能用二進(jìn)制來儲存東西(0,1),所以在計(jì)算機(jī)就變成了m*2^e。m我們稱之為尾數(shù),e稱之為階碼。同時(shí)我們也就得到等式:

A*10^B = m*2^e

但還沒完,就這樣還遠(yuǎn)遠(yuǎn)不夠。
下面先求對于位數(shù)下 me 的最大值
對于小數(shù),10進(jìn)制可以用 a1*10^(-1) + a2*10^(-2) + ... + an*10^(-n)的方式表示。2進(jìn)制的情況顯然相似(對于用 i 位進(jìn)行儲存):

m = 2^(-1) + 2^(-2) + ... + 2^(-1 - i)
= 1 - 2^(-1 - i)

e 則好辦多了:

e = 2^j - 1

題目給出了0 ≤ M ≤ 9,1 ≤ E ≤ 30(M,E分別為尾數(shù)和階碼的位數(shù)),所以最多共有300種表示方法,進(jìn)而聯(lián)想到打表。用兩個二維數(shù)組,分別儲存對應(yīng)位數(shù)時(shí)的尾數(shù)和階碼的最大值,分別記為M[i][j]和E[i][j]。

然后接下來到計(jì)算對應(yīng) M 和 E 的值。還記得剛剛的等式嗎?對,我們需要借助那個。對兩邊取十為底的對數(shù)lg:

lg(A) + B = lg(m) + e*lg(2) = t

由于A小于10,所以lg(A)就是 t 的小數(shù)部分,自然 B 就是 t 的整數(shù)部分。
所以,我們的 E[i][j] 只需在計(jì)算出 t 之后取整即可。M[i][j] 則為:

10^( t - E[i][j] )

即可。(取10的冪是為了方便與A比較,就無需計(jì)算lg(A)了 )

搞定了M和E,就到讀入 AB 了。
因?yàn)檩斎氲母袷且粋€字符串,所以考慮先當(dāng)成字符串儲存再進(jìn)行處理。觀察結(jié)構(gòu)可以把e換成空格,然后用函數(shù)sscanf()進(jìn)行輸入。

最后進(jìn)行遍歷匹配即可。不過因?yàn)楦↑c(diǎn)數(shù)自身精確度的問題,會存在誤差,所以還需設(shè)一個誤差范圍。此題誤差設(shè)為 1e-4 效果最好。

代碼

#include <stdio.h>
#include <math.h>
#include <string.h>

//多層循環(huán)用函數(shù)更容易跳出
void solve(double m, int e);
double M[12][33];   //儲存尾數(shù)表
long long E[12][33];  //儲存階數(shù)表

int main() {
#ifdef TEST
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif // TEST

    //打表
    int i, j;
    char str[25];
    for (i = 0; i <= 9; ++i) for (j = 1; j <= 30; ++j) {
        double m = 1 - pow(2, -1 - i), e = pow(2, j) - 1;
        double t = log10(m) + e * log10(2);
        E[i][j] = t, M[i][j] = pow(10, t - E[i][j]);
    }

    //讀入處理
    while (scanf("%s", str) == 1 && strcmp(str, "0e0")) {
        double A; int B;
        * (strchr(str, 'e')) = ' ';
        sscanf(str, "%lf %d", &A, &B);
        while (A < 1) A *= 10, B -= 1;
        solve(A, B);
    }

    return 0;
}

void solve(double m, int e) {
    for (int i = 0; i <= 9; i++)
        for (int j = 1; j <= 30; j++)
            if (e == E[i][j] && (fabs(m - M[i][j]) < 1e-4 || fabs(m / 10 - M[i][j]) < 1e-4)) {
                printf("%d %d\n", i, j);
                return;
            }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容