UVA

/*

  这份代码参考了这个博客中的思路:
  http://blog.csdn.net/crazysillynerd/article/details/43339157
  感谢这个博主,一开始我是不知道怎么处理这么大的数据的,还要多亏了他博客的细致讲解...在做这题的ACMer们可以去看看,博主分析得十分到位,无论是数学公式的一步步推理过程,打表时的各种考虑,还是对于数据不是科学记数法表示的处理方法等等...看完受益匪浅
  
  来梳理一下这题的思路:
  ①数学公式推理,包括:
  从M和E的位数推出M和E(这个公式的推理,和计算机系统里学的IEEE浮点数表示规则有些关系,不过题目也已经描述得比较清楚了)
  
  从M和E表示的浮点数 M * (2 ^ e) 推出十进制下和它相等的 A * 10B 中的A和B(这个用两边取对数的方法来算)
  
  ②打表,建立M、E位数和A、B的关系,并通过前者求出对应的后者,存入数组
  
  ③考虑精度 浮点数据的精度,以及题目要求的精度,等等,因此对应数组中的数据,和B未必严格相等,要做1e-4的精度处理
  
  ④特殊情况的考虑:
  题目只是保证输入中 A范围为(0, 10),而不是我们按照十进制的数据规则期待的[1,10),那么对于(0,1)的数据情况,就需要先变成[1,10)这个范围了(应先做这个处理: A *= 10, B--)
  
  再次感谢大神的blog写得如此细致,让我对这题从一知半解到有些熟悉,再放大神的blog
  http://blog.csdn.net/crazysillynerd/article/details/43339157
  
  另外,代码中用了字符串处理的函数,是为了把A和B从输入数据中分离出来,因为并不知道何时出现e
*/


#include <iostream>
#include <string>
#include <sstream>
#include <cmath>
using namespace std;

int main()
{
	double M[20][40];
	long long E[20][40];
	
	// 打表
	for (int i = 0; i <= 9; i++)
	for (int j = 1; j <= 30; j++)
	{
		double m = 1 - pow(2, -1 - i), e = pow(2, j) - 1;
		double t = log10(m) + e * log10(2);
		E[i][j] = t, M[i][j] = pow(10, t - E[i][j]);
	} 
	
	// 输入输出结果
	string in;
	while (cin >> in && in != "0e0")
	{
		for (string::iterator i = in.begin(); i != in.end(); i++)
			if (*i == 'e') *i = ' ';
		
			istringstream ss(in);
			double A; int B;
			ss >> A >> B;
			//换为科学计数法的表示方式 
			while (A < 1) A *= 10, B -= 1;
			//表中找答案 
			for (int i = 0; i <= 9; i++)
			for (int j = 1; j <= 30; j++)
			{
				if (B == E[i][j] && ( fabs(A - M[i][j]) < 1e-4 ) )
				{
					cout << i << ' ' << j << endl;
					break; 
				}
			}
	} 
	return 0;
}



原文地址:https://www.cnblogs.com/mofushaohua/p/7789543.html