UVa 11809:Floating-Point Numbers

題目傳送門:UVa 11809:Floating-Point Numbers

這道題弄了幾個小時才AC。首先觀察下題目的輸入輸出:

Input

The input file contains around 300 line of input. Each line contains a floating-point number F that denotes the maximum value that can be represented by a certain floating-point type. The floating point number is expressed in decimal exponent format. So a number AeB actually denotes the value A×10B. A line containing ‘0e0’ terminates input. The value of A will satisfy the constraint 0 < A < 10 and will have exactly 15 digits after the decimal point.

Output

For each line of input produce one line of output. This line contains the value of M and E. You can assume that each of the inputs (except the last one) has a possible and unique solution. You can also assume that inputs will be such that the value of M and E will follow the constraints: 9 ≥ M ≥ 0 and 30 ≥ E ≥ 1. Also there is no need to assume that (M + E + 2) will be a multiple of 8.

Sample Input

5.699141892149156e76
9.205357638345294e18
0e0

Sample Output

5 8
8 6


題目的輸出提到 9 ≥ M ≥ 0 and 30 ≥ E ≥ 1,所以我們可以打表,把尾數二進制位數在 0-9 之間,階碼位數在 1-30 之間的所有最大值都存起來(打表)。

需要注意一點的是,階碼最大的位數爲 30,也就是說指數最大爲 2^30 - 1,所以說 2 的 2^30 - 1 次方會超範圍。

令尾數爲 m,階碼爲 e,輸入中有AeB,則他們有如下關係:

m×2e=A×10B

這裏的 e 最大爲 2^30 - 1,會超範圍,所以我們可以對等式兩邊取對數:
log10(m×2e)=log10(A×10B)

等價於:
log10m+e×log102=log10A+B

題目中還提到 0 < A < 10,所以 log10A<1 是一個小數,因爲B一定是一個整數,所以 B=(int)(log10m+e×log102) ,即直接取整即可。所以此時有:

B=(int)(log10m+e×log102)A=10log10m+e×log102B

所以,我們只要保存M和E對應的A和B,然後查表即可。

AC代碼如下:

#include <stdio.h>
#include <string.h>
#include <math.h>
double M[15][35];
int E[15][35];

void init()
{
    int i, j;
    for (i = 0; i <= 9; ++i)
    {
        for (j = 1; j <= 30; ++j)
        {
            long long e = pow(2, j) - 1; // 階碼
            double m = 1 - pow(2, -(i+1)); // 尾數
            double t = log10(m) + e * log10(2);
            E[i][j] = t;
            M[i][j] = pow(10, t - E[i][j]);
        }
    }
}

int main()
{
    init();
    char str[25];
    while (1 == scanf("%s", str))
    {
        if (0 == strcmp(str, "0e0"))
            return 0;
        str[17] = ' '; // str[17]是字符e
        double a; int b;
        sscanf(str, "%lf %d", &a, &b); // 從字符串輸入
        int i, j, flag = 0;
        for (i = 0; i <= 9; ++i) // 查表
        {
            for (j = 1; j <= 30; ++j)
            {
                if (b == E[i][j] && fabs(a - M[i][j]) < 1e-4) // 注意判斷double是否相等時的精度問題
                {
                    printf("%d %d\n", i, j);
                    flag = 1;
                }
            if (flag) break;
            }
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章