POJ1001Exponentiation,已AC

求高精度幂
Time Limit: 500MS Memory Limit: 10000K
Total Submissions: 170398 Accepted: 41283

Description

对数值很大、精度很高的数进行高精度计算是一类十分常见的问题。比如,对国债进行计算就是属于这类问题。 

现在要你解决的问题是:对一个实数R( 0.0 < R < 99.999 ),要求写程序精确计算 R 的 n 次方(R n),其中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

Sample Output

548815620517731830194541.899025343415715973535967221869852721
.00000005148554641076956121994511276767154838481760200726351203835429763013462401
43992025569.928573701266488041146654993318703707511666295476720493953024
29448126.764121021618164430206909037173276672
90429072743629540498.107596019456651774561044010001
1.126825030131969720661201
题目分析:
 
由于该题数字太大,用pow函数是无法解决的,所以我们需要用字符数组来解决问题,采用STL创建一个string类型的可变数组可以方便我们进行操作。所需的步骤有六步:
①输入处理:由于我们正常输入,最高位是存在数组的最低位,所以我们需要先对其进行处理,将其倒置,并去掉小数点,并记录小数点的位置。
②模拟手算的过程:用mul表示每一次被乘的数(记得每乘完一个数都要将结果放入mul用于下一次运算),将乘数用一个数组ori记录(就等于输入的数据,因为它是不会变的),再用一个tmp数组存储每一位数操作得出的结果,用res数组存储总的结果(res是每一次tmp结果相加)具体过程看代码标注。
③插入小数点:用一个迭代器找到所需插入的位置,用insert函数即可,然后将mul数组(我最后懒得再将res=mul)翻转便于后面输出
④去除多余的0:用left和right分别代表小数点的左边和右边,找到有效数字的位置,最后根据left和right的位置进行输出。(要考虑是否有小数)
⑤最后就是简单的循环输出咯  代码中还有更详细的解释。
测试数据网上可以搜到,可以去看看自己哪一步错了。
话不多说(好像挺啰嗦的),看代码
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;

int main()
{
    string inp;//接收数据;
    string mul;//处理后的数据
    string res;//最终数据
    int n;//阶乘
    while(cin>>inp>>n)
    {
        res="0";
        int len_inp=int(inp.length());
        int pos=0;//小数点位置
        for(int i=len_inp-1;i>=0;i--)//寻找小数点并且将数据存入新的s
        {
            if(inp[i]!='.')
                mul+=inp[i];
            else
                pos=len_inp-i-1;
        }
        string tmp;//每乘一个数的结果
        int mul_cnt;//乘数
        int len_mul = len_inp-1;
        int i,j;
        int res_len = len_mul;
        res=mul;
        pos=pos*n;//小数点最终位置
        string ori=mul;//每次乘的数
        while(n--)
        {
            
            mul.clear();
            mul=res;//重新定义被乘数
            len_mul=res_len;//重新规定被乘数的长度
            for(i=0;i<len_inp-1;i++)//第一重,原始数据的每一个数
            {
                mul_cnt=ori[i]-'0';
                int jinwei=0;
                for(j=0;j<len_mul;j++)//第二重,乘数乘以被乘数的每一个数字
                {
                    int fir_cnt=0;
                    fir_cnt=(mul_cnt*(mul[j]-'0')+jinwei)%10;//当前个位数结果
                    jinwei=(mul_cnt*(mul[j]-'0')+jinwei)/10;//十位数结果
                    tmp+=fir_cnt+'0';//存入tmp中
                }
                if(jinwei)//如果被乘数的最后一位乘完还有进位,则需在tmp后多加一位
                    tmp+=jinwei+'0';
                if(i==0)//因为乘法中第一次乘不用与原来的相加。手算的第一步
                {
                    res.clear();//有点多余,保险
                    res=tmp;//直接等于就好
                }
                else
                {
                    if(res.length()<(tmp.length()+i))//因为相加需要移位,为了方便,将他们的位数都用0补齐
                    {
                        int cha=int(tmp.length()-res.length())+i;//i是所需移位的距离
                        while(cha--)
                        {
                            res+='0';
                        }
                    }
                    int jinwei=0;
                    int x;
                    for(x=0;x<tmp.length();x++)
                    {
                        int sum=(res[x+i]-'0'+tmp[x]-'0')+jinwei;//将他们的字符提出来int化
                        jinwei=0;
                        if(sum>=10)
                        {
                            sum%=10;
                            jinwei=1;
                        }
                        res[x+i]=sum+'0';
                    }
                    if(jinwei)//与前面一样
                        res+='1';
                }
                res_len=int(res.length());//千万要记得重新测量长度,否则下次就不知道要乘几位数了
                tmp.clear();//将这次的结果清零
            }
        }
        //清零与输出操作
        string::iterator it;
        it=mul.begin();
        mul.insert(it+pos,'.');//找到位置插入
        reverse(mul.begin(), mul.end());
        int co_pos=int(mul.find('.'));//找出小数点的位置
        int left,right;
        //分别从最左边与最右边开始,遇到非零就停下
        for(left=0;left<co_pos;left++)
        {
            if(mul[left]!='0')
                break;
        }
        for(right=int(mul.length())-1;right>co_pos;right--)
        {
            if(mul[right]!='0')
                break;
        }
        if(right==co_pos)//特别注意当没有小数的时候
        {
            for(int i=left;i<right;i++)
                cout<<mul[i];
        }
        else
        {
            for(int i=left;i<=right;i++)
                cout<<mul[i];
        }
        cout<<endl;
        mul.clear();//记得清零,这一组数据结束
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值