原题链接:http://poj.org/problem?id=1001
分类:高精度计算
算法:按照小学生手算的方法进行计算,利用字符串对数字进行处理。
c++源代码:
1 #include<iostream> 2 #include<string> 3 #include<vector> 4 5 using namespace std; 6 7 string times_func(string s1, string s2); // 用于计算两个大数的乘法(高精度乘法) 8 string solve(string s, int n); // 用于计算整数阶乘 9 10 int main() 11 { 12 string s; 13 int n; 14 while(cin >> s >> n) 15 { 16 int index = s.find_first_of("."); // 定位小数点在字符串中的位置 17 int m = s.length() - index - 1; 18 // 首先将带小数点的数变为整数类型,这里用了C++ String 的迭代器 19 for (string::iterator it = s.begin(); it != s.end(); ++it) 20 { 21 if (*it == '.') 22 { 23 s.erase(it); 24 break; 25 } 26 } 27 string result = solve(s,n); // 此处获得的是一个整数的阶乘解 28 int k = 0; 29 string::iterator it; // k为控制小数点位置的标识 30 for (it = result.end(); k <= m*n; k++, --it) {} 31 result.insert(++it,'.'); // 在相应位置插入小数点,如果小数点后为m位,其n次方通常为m*n位小数 32 // 处理小数点都为0的情况 33 index = 0; 34 for (int i = 0; result[i] != '.'; i++) 35 { 36 if (result[i] != '0') break; 37 else index++; 38 } 39 result = result.substr(index,result.length()); 40 // 处理小数点末尾连续为0的情况 41 index = 0; 42 for (int i = result.length()-1; result[i] != '.'; i--) 43 { 44 if (result[i] != '0') break; 45 else index++; 46 } 47 result = result.substr(0,result.length()-index); 48 int l = result.length(); 49 // 处理整数情况 50 if (result[l-1] == '.') result = result.substr(0,l-1); 51 cout << result << endl; 52 } 53 return 0; 54 } 55 56 // 高精度阶乘 57 string solve(string s, int n) 58 { 59 string result = s; 60 for (int i = 1; i < n; i++) 61 { 62 string tmp = ""; 63 tmp = times_func(result,s); 64 result = ""; 65 for (int i = tmp.length()-1; i>=0; i--) result += tmp[i]; 66 } 67 return result; 68 } 69 70 // 高精度乘法 71 string times_func(string s1, string s2) 72 { 73 int n1 = s1.length(); 74 int n2 = s2.length(); 75 vector<string> nums; 76 string result = ""; 77 for (int i = n1-1; i >= 0; i--) 78 { 79 int m; 80 int carry = 0; 81 string tmp = ""; 82 for (int j = i; j < n1-1; j++) tmp += '0'; 83 for (int j = n2-1; j >= 0; j--) 84 { 85 m = ((s1[i]-48) * (s2[j]-48) + carry) % 10; 86 carry = ((s1[i]-48) * (s2[j]-48) + carry) / 10; 87 tmp += (char)(m+48); 88 } 89 if (carry > 0) tmp += (char)(carry+48); 90 nums.push_back(tmp); 91 92 } 93 94 // 高精度乘法中包含了高精度加法的运算 95 if (nums.size() != 0) result = nums[0]; 96 for (int i = 1; i < nums.size(); i++) 97 { 98 string tmp = nums[i]; 99 int l = tmp.length(); 100 int c = 0; 101 int k = 0; 102 for (int j = 0; j < result.length(); j++,k++) 103 { 104 if(result[j]+tmp[k]+c-96 >= 10) 105 { 106 result[j] = result[j]+tmp[k]+c-48-10; 107 c = 1; 108 } 109 else 110 { 111 result[j] = result[j]+tmp[k]+c-48; 112 c = 0; 113 } 114 } 115 for (; k<l; k++) 116 { 117 if(tmp[k]+c-48 >= 10) 118 { 119 result.push_back(tmp[k]+c-10); 120 c = 1; 121 } 122 else 123 { 124 result.push_back(tmp[k]+c); 125 c = 0; 126 } 127 } 128 if (c == 1) result.push_back('1'); 129 } 130 131 return result; 132 }
后续工作思考:由于高精度计算本质上是对字符串的处理,因此上述代码用到了C++中标准的STL库,如Vector,String,这给本题的求解带来很大的便利。但是后来查看了题源,为1988年的题目,很老,那时候应该只有pascal,c以及非标准的C++,标准C++中的STL库还没有出现,因此其实本题最好用C语言重新实现,在有空的时候重写一下。