/* 这份代码参考了这个博客中的思路: 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; }