UVa 11809 - Floating-Point Numbers

  本道题是刘汝佳《入门经典》第三章的最后一道竞赛题,第一次看的时候,完全不知所云,虽然刚刚学完浮点数的表达,但应用的话,还是小白一个。。。看了半天就先搁置了,去看第四章,结果第四章的习题又被虐惨了,什么约瑟夫环,信息编码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;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值