本道题是刘汝佳《入门经典》第三章的最后一道竞赛题,第一次看的时候,完全不知所云,虽然刚刚学完浮点数的表达,但应用的话,还是小白一个。。。看了半天就先搁置了,去看第四章,结果第四章的习题又被虐惨了,什么约瑟夫环,信息编码ORZ,感觉智商被严重碾压,所以只能滚回来先看这道。好吧,这道题自己没有思路,看了好多博客,大致知道怎么写了,而且有很多精妙的地方和值得注意的地方,对现阶段的我来说,这道题真的能够很好的提升我的能力,总结如下:
一.编代码之前必须要想好思路,大致框架如何,是要自顶向下(先把框架搭起来,然后逐一完善细节),还是自底向上(根据已经写好的类、函数这些细节来确定总体的具体完成情况)。比如本题要解决的问题有这几个:
1.输入问题:如何表示输入的数据。
2.转换问题:进制之间的转换,如何存储(有数学公式法和递推法,不在赘述)
3.查找问题:输入和输出如何一一对应,如何实现算法,效率会更高。
4.细节问题:这道题有很多考察细节的地方,比如如何识别AeB中的 ‘e’ 从而分离出A和B,还有精度转换,string到double的转换
二.一些小技巧:
1.学会 istringstream 的使用,是一个输入输出控制类型,在此题中用来将string类型 转换为 double类型,具体用法详见http://blog.sina.com.cn/s/blog_a9303fd90101adt6.html
2.浮点数不能用 ‘==’ 去判断,因为有误差,需要fabs(A-B)< 1e-5; 这种格式去表示
3.注意枚举打表法的使用,当数据量不多的时候,可用此法,反过来解题也许会容易一些
4.多用函数,这样写出来的代码好看
这是我的代码,继续加油啦!
#include<iostream>
#include<sstream>
#include<string>
#include<math.h>
double M[20][40];
long long E[20][40];
using namespace std;
//打表法,遍历所有i和j,求出M和E两张表,分别表示尾数和阶码
void make_table();
//通过输入的in,按表查找,求得结果
void obtain_bit_number(string& in);
int main(void)
{
int hhh;
make_table();
string in;
while (cin >> in && in != "0e0")
{
obtain_bit_number(in);
}
return 0;
}
void make_table()
{
for (int i = 0; i < 10; i++)
{
double m = 1 - pow(2, -i - 1);
for (int j = 1; j <= 30; j++)
{
double e = pow(2, j) - 1; //可以直接用数学公式,如此做法。也可以用迭代的方式,一步一步算
double t = log10(m) + e * log10(2); //数学推导
//这里把尾数和阶码看做科学技术法的形式,但题目中并不是,因为M有可能在(0,1)之间
E[i][j] = floor(t); //阶码等于t取整
M[i][j] = pow(10, t - E[i][j]); //log10(尾数)等于t的小数部分
}
}
return;
}
void obtain_bit_number(string& in)
{
for (auto i = in.begin(); i != in.end(); i++)
{
if (*i == 'e') *i = ' ';
}
istringstream ss(in);
double A; //尾数 同时进行 字符到浮点的隐式转换
int B; //阶码 同时进行 字符到浮点的隐式转换
ss >> A >> B;
for (int i = 0; i < 10; i++)
{
int flag = 0;
flag = 0;
for (int j = 1; j <= 30; j++)
{
if (fabs(B-E[i][j]) < 1e-4 && fabs(A - M[i][j]) < 1e-4)
{
cout << i << " " << j << endl;
flag = 1;
break;
}
}
if (flag) break;
}
}