题目如下:
Description
Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems.
This problem requires that you write a program to compute the exact value of R n where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25.Input
The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9.Output
The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don't print the decimal point if the result is an integer.
大数高精度计算,通常都是用字符串来存储数据的每一位,分而求之。
对于本题,我的想法是:
由于两个数相乘,其结果为一个因数的各个位分别乘以另一个因数的积之和。比如:
1314 × 520 可以视作:0 × 1314 + 20 × 1314 + 500 × 1314
=> 0 × 1314 × 1 + 2 × 1314 × 10 + 5 × 1314 × 100
我先编写了一个plus函数,用来计算两数相加的和。
在编写plus函数时,发现我们通常手算加法的时候,都是从低位开始相加,并且当同位上的两个数相加>=10的时候,要向较高位进1。但是,在程序中,若按一般的逻辑,我们会把较高位放在string(字符串)的开头(左边),较低位放在末尾(右边),这样的顺序会导致我们在计算过程中,加大了进位或其他操作的复杂度。而若是按相反的顺序来存放,计算就方便得多了。(如数字123,存储顺序为321)。
然后编写了multiply函数,在函数中调用plus,得出两个数的乘积。
然而,提交后发现这种方法效率过低,系统给了个Output Limit Exceeded
继续思考改进方法。。。
以下为代码(低效):
#include <iostream> #include <string> #include <iterator> using namespace std; void inverted_sequence(string& s) { char temp; for (int i = 0, j = s.size() - 1; i < j; i++, j--) { temp = s[i]; s[i] = s[j]; s[j] = temp; } } void plus(string& out, string s1, string s2) { int i; string* s; string t = ""; i = s1.size() - s2.size(); if (i < 0) { i *= -1; s = &s1; } else s = &s2; for (; i > 0; i--) s->push_back('0'); s1.push_back('0'); s2.push_back('0'); int a, b, sum; for (i = 0; i < (int)s1.size(); i++) { a = s1[i] - '0'; b = s2[i] - '0'; sum = a + b; if (sum >= 10) { t.push_back(sum % 10 + '0'); for (int j = i + 1; j < (int)s1.size(); j++) { a = s1[j] - '0'; a++; s1[j] = a % 10 + '0'; if (a < 10) break; } } else t.push_back(sum + '0'); } i = (int)t.size() - 1; if (t[i] == '0') t.erase(i, 1); out = t; } void multiply(string& out, string s1, string s2) { int n = (int)s1.size(); int m = (int)s2.size(); string* prdct = new string[n]; string* sum = new string[m]; int i, j, k; for (i = 0; i < n; i++) prdct[i] = ""; for (i = 0; i < m; i++) sum[i] = "0"; int a, b, r; for (i = 0; i < m; i++) { b = s2[i] - '0'; for (j = 0; j < n; j++) { a = s1[j] - '0'; r = a * b; for (k = 0; k < j; k++) prdct[j] = prdct[j] + "0"; for (k = 1; r / k >= 1; k *= 10) prdct[j].push_back(r / k % 10 + '0'); } for (j = 0; j < n; j++) { plus(sum[i], sum[i], prdct[j]); prdct[j] = ""; } for (k = 0; k < i; k++) sum[i].insert(0, "0"); } out = "0"; for (i = 0; i < m; i++) plus(out, out, sum[i]); delete [] prdct; delete [] sum; } void initialize(string& s, const int n, int& pn) { string::iterator iter; iter = s.begin(); while (iter != s.end() && *iter == '0') ++iter; if (iter != s.begin()) s.erase(s.begin(), iter); inverted_sequence(s); iter = s.begin(); while (iter != s.end() && *iter == '0') ++iter; if (iter != s.begin()) s.erase(s.begin(), iter); for (int i = 0, size = (int)s.size(); i < size; i++) { if (s[i] == '.') { pn = i; break; } } if (pn) { s.erase(pn, 1); pn *= n; } else pn = -1; } void exponentiation(string& out, string& base_number, int n) { string square; string prdct = "1"; int pn = 0; int m = n; initialize(base_number, n, pn); if(base_number == "") { out = "0"; return; } if(n == 0) { out = "1"; return; } multiply(square, base_number, base_number); for(int i = 0; i < m / 2; i++) { multiply(prdct, square, prdct); } if (n % 2) multiply(prdct, prdct, base_number); while ((int)prdct.size() < pn) prdct.push_back('0'); if(pn >= 0) prdct.insert(pn, "."); inverted_sequence(prdct); out = prdct; } int main(void) { string s; int n = 0; while(n != -1) { cin >> s >> n; exponentiation(s, s, n); cout << s << endl; } return 0; }
POJ_1001(Exponentiation) 求高精度幂 攻略中...
最新推荐文章于 2021-03-14 17:02:10 发布