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;
}
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页