求高精度幂(poj 1001)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_25203255/article/details/78847023

1 问题描述

Description

对数值很大、精度很高的数进行高精度计算是一类十分常见的问题。比如,对国债进行计算就是属于这类问题。
现在要你解决的问题是:对一个实数R( 0.0 < R < 99.999 ),要求写程序精确计算 R 的 n 次方(Rn),其中n 是整数并且 0 < n <= 25。

Input

T输入包括多组 R 和 n。 R 的值占第 1 到第 6 列,n 的值占第 8 和第 9 列。

Output

对于每组输入,要求输出一行,该行包含精确的 R 的 n 次方。输出需要去掉前导的 0 后不要的 0 。如果输出是整数,不要输出小数点。

Sample Input

95.123 12
0.4321 20
5.1234 15
6.7592 9
98.999 10
1.0100 12

题目地址 poj 1001

2 算法实现

#include <iostream>
#include <string>
#include <vector>

using namespace std;

// 进位调整
void carry_bit(vector<int>& n) {
    // 从后向前进行进位, 默认进位值C=0
    int i, C = 0;
    for(i = n.size() - 1; i >= 0; -- i) {
        int v = n[i] + C;
        n[i] = v % 10;
        C = v / 10;
        // 第一位也需要进位的情况
        if(C && !i) n.insert(n.begin(), C);
    }
}

// n1 乘数 n2 被乘数
vector<int> mul(const vector<int>& n1, const vector<int>& n2) {
    vector<int> result;
    int i, j;
    // n1每位数从前向后(简化调位操作)和n2相乘
    for(i = 0; i < n1.size(); ++ i) {
        vector<int> t;
        for(j = 0; j < n2.size(); ++ j)
            t.push_back(n2[j] * n1[i]);
        // 如果i = 0直接复制到result中
        if(i == 0) result = t;
        else {
            // 先调位
            carry_bit(t);
            // 错位相加,最后1为无数可加,直接复制到最后面
            int k = t.size() - 1;
            result.push_back(t[k--]);
            // 剩余的数和部分积相加
            for(j = result.size() - 2; j >=0 && k >=0 ; -- j, -- k)
                result[j] += t[k];
        }
        // 对部分积调位
        carry_bit(result);
    }
    return result;
}

// 去掉前导的 0 后不要的 0
int toList(string& s, vector<int>& out) {
    int dot = 0, i;
    // 去掉最前面的0
    for(i = 0; i < s.size() && s.size() != 1; ) {
        if(s[i] != '0' || (s[i] == '0' && s[i + 1] == '.')) break;
        if(s[i] == '0') s.erase(i, 1);
    }
    // 如果存在小数点,去掉最后面的0
    for(i = s.size() - 1; i >= 0 && s.find('.'); ) {
        if(s[i] == '.') {
            s.erase(i, 1);
            break;
        }
        else if(s[i] == '0') s.erase(i --, 1);
        else break;
    }
    // 分割每一个数字,不使用小数点参与运算
    for(i = 0; i < s.size(); ++ i) {
        if(s[i] == '.') dot = i;
        else out.push_back(s[i]-'0');
    }
    return dot;
}

int main()
{
    string s;
    int n;
    while(cin>>s>>n) {
        vector<int> v;
        int i, k, d = toList(s, v);
        vector<int> result = v;
        for(i = 1; i < n; ++ i)
            result = mul(v, result);
        // 计算小数点位置
        k = result.size() - (v.size() - d) * n - 1;
        // 乘数为0的情况
        if(result.empty()) cout << "0";
        for(i = 0; i < result.size(); ++ i) {
            if(d) {
                // 第一位是0同时紧跟小数点的情况=> .xxxx
                if(!(!k  && !result[i] && !i)) cout << result[i];
                if(i == k) cout << ".";
            }
            // 无小数点的情况
            else cout << result[i];
        }
        cout << endl;
    }
    return 0;
}

3 数据测试


这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_25203255/article/details/78847023
今日推荐