Floating-Point Numbers的真·暴力与暴力解法

紫书第三章最后一道,,,自从寒假就没碰紫书的题,,现在补一下,,

Floating-Point Numbers UVA - 11809

题意:你以为我是模拟??其实我是数学题哒!给你一个用科学计数法表示的数字,让你计算在内存中以浮点数储存时占据的尾速部分和指数部分的位数;

题解:我们要求的时位数占位M,和指数占位E M能表示的最大尾数为: \(a = 2^{-1} + 2^{-2} + ... + 2^{-m-1}\) 可以处理为:\(a = 1 - 2^{-m-1}\) E能表示的最大阶乘:\(b = 2^{2^E - 1}\)

所以: \[a * 2^b = A * 10^B\]

而且这道题的m和e的范围非常小; 可以打表然后判断解决;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const double Min = 1e-5;
double lis[10][31];
ll jie[10][31];

void dab(){
for(int m = 0; m < 10; m++)
for(int e = 1; e < 31; e++){
double a = 1.0 - pow(2.0, -1.0*m-1.0);
double b = pow(2.0, e) - 1.0;
jie[m][e] = floor(log10(a) + b * log10(2));
lis[m][e] = pow(10, log10(a) + b * log10(2) - 1.0*jie[m][e]);
}
}

int main(){
dab();
double a;
ll b;
while(~scanf("%17lfe%lld", &a, &b) && a > Min){
int m, e;
for(e = 1; e < 31; e++)
for(m = 9; m >= 0; m--)
if(b == jie[m][e] && fabs(lis[m][e] - a) < Min)goto out;
out: printf("%d %d\n", m, e);
}

return 0;
}

但如果想要更加暴力呢? 当然是可以的,直接算出答案,模糊判断输入数据AeB的M和E,直接输出M和E; 就是误差控制不好控制,,要优化减小误差,同时考虑误差,wa了好多次,,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<bits/stdc++.h>
using namespace std;

const double Min = 1e-6;

int main(){
double a;
int b;
while(~scanf("%17lfe%d", &a, &b) && (a > Min || b)){
if(a < Min)break;
double d = ceil((b + log10(a)) / log10(2) + 1e-4);
double e = ceil(log2(d + 1));
double c = pow(2, (b + log10(a)) / log10(2) - d);
double m = abs(ceil(-log2(1 - c) -1 - 1e-4));
printf("%.0lf %.0lf\n", m, e);
}

return 0;
}

Comments

2019-02-28
Contents

⬆︎TOP