poj 1001 浮点数高精度求幂

//===================================//
//
//    poj:1001 浮点数求幂
//  完成时间:2010.09.07
//
//==================================//
#include <iostream>
#include <stdlib.h>
#include <string>

const int MAX_LEN = 150;

using namespace std;

int StringConvert(const string &str, int &t);    //字符串转换int
int BigNumAdd(int *buf, int q, int ilen);    //大数加法

unsigned int x1[MAX_LEN * 2 + 10];
unsigned int x2[MAX_LEN + 10];
unsigned int result[MAX_LEN * 2 + 10];

int main()
{
    string R;    //输入的实数
    int N;        //幂次方
   
    while(cin >> R >> N)
    {
        int decialNum = 0;    //保存小数点位数
        int ilen = 0;    //
        int t = 0;        //字符串转换完成int数组后保存数组长度
        bool nozero = false; //用于不计算前导0 ilen保存数的长度
        memset(x1, 0, sizeof(x1));
        memset(x2, 0, sizeof(x2));
        memset(result, 0, sizeof(result));
       
        decialNum = StringConvert(R, t);    //将字符串转换并返回小数点位数

        for (int j=t-1; j>=0; j--)
        {
            //判断用于去除int数组中的前导0
            if (x2[j] != 0)
            {
                nozero = true;
                x1[j] = x2[j];
                ilen++;
            }
            else
            {
                if (!nozero)
                {
                    continue;
                }
                else
                {
                    x1[j] = x2[j];
                    ilen++;
                }
            }
        }
       
        int iresultLen = 0;    //计算结果的数组长度
        int ixlen = ilen;    //x1保存的是被乘数
       
        if (N == 0)        //任何数的0次方为1
        {
            cout << "1" << endl;
        }
        else if (N == 1)    //任何数的1次方为其本身
        {
            if (decialNum >= ilen) //当小数位数大于数的长度时
            {
                //直接忽略前导0输出小数点
                cout << '.';
               
                //根据小数点和数字位数差来决定输出几个零
                for (int b=0; b<decialNum-ilen; b++)
                {
                    cout << '0';
                }
               
                //输出数组中保存的数
                for (int c=ilen-1; c>=0; c--)
                {
                    cout << x2[c];
                }
            }
            else    //当小数位数小于数的位数时
            {
                bool label = false; //用于判断小数点是否已打印
               
                for (int d=ilen-1; d>=0; d--)
                {
                    //当到达打印小数点的位置时打印小数点
                    if (d == decialNum - 1 && !label)
                    {
                        cout << '.';
                        d++;
                        label = true;
                    }
                    else
                    {
                        cout << x2[d];
                    }
                }
            }

            cout << endl;
        }
        else    //除了0次方和1次方以外的情况
        {
            int n = N;    //保存次方数和初始小数点位数相乘用于计算最后小数点的位数

            N--;   
           
            while (N--)
            {
                if (iresultLen)    //当结果数组的长度为0时代表此时为第一次乘法
                {
                    memset(x1, 0, sizeof(x1));
                   
                    //将上一次的结果保存为被乘数以便进行下一次运算
                    for (int i=0; i<iresultLen; i++)
                    {
                        x1[i] = result[i];
                        ixlen = iresultLen;
                    }
                }
               
                memset(result, 0, sizeof(result));    //结果必须清零否则上次数据将被使用
               
                //ilen保存乘数个位数,以确定做几次乘法
                for (int q=0; q<ilen; q++)
                {   
                    int z = 0;  //进位
                    int buf[MAX_LEN * 2 + 10] = {0};    //临时保存结果
                   
                    for (int y=0; y<ixlen; y++)
                    {
                        int tmp;
                       
                        tmp = x1[y] * x2[q] + z;    //从各位开始做乘法,初始进位为0
                        buf[y] = tmp % 10;    //求模取结果
                        z = tmp / 10;        //除法取进位
                    }
                   
                    int ibufLen = ixlen;    //用于保存将传递的一次乘法结果的位数
                   
                    if (z)    //查看进位是否为0如果为0则不计算不为0则在结果的最高位的下一位赋值
                    {   
                        buf[ixlen] = z;
                        ++ibufLen;
                    }
                   
                    iresultLen = BigNumAdd(buf, q, ibufLen); //将一次乘法结果与上次乘法结果相加并返回结果位数
                }   
            }
       
            if (decialNum * n >= iresultLen)    //输出类似1次方的输出,区别为要考虑小数点位数
            {
                cout << '.';
               
                for (int i=0; i<decialNum*n-iresultLen; i++)
                {
                    cout << '0';
                }
               
               
                for (int l=iresultLen-1; l>=0; l--)
                {
                    cout << result[l];
                }
            }
            else
            {
                bool label = false;
               
                for (int d=iresultLen-1; d>=0; d--)
                {
                    if (d == decialNum * n - 1 && !label)
                    {
                        cout << '.';
                        d++;
                        label = true;
                    }
                    else
                    {
                        cout << result[d];
                    }
                }
            }

            cout << endl;
        }
    }

    return 0;
}

//字符串结果转换保存到int数组中,并返回数组元素个数和小数点位数
int StringConvert(const string &str, int &t)
{
    int decialNum = 0;
    bool label = false;    //标识是否已经遇到非零的数
    int iRsize = str.size();
   
    //数据都从个位向高位保存
    for (int i=iRsize-1; i>=0; i--)
    {
        char temp;
        int k;    //忽略了所有浮点数尾部的0以后有效值的开始位置
       
        temp = str[i];
       
        if (temp != '0')    //判断字符是否为0
        {   
            if (!label)        //且遇0标识为false表示第一次遇到非0数
            {
                k = i;   
                label = true;
            }
           
            if (temp == '.')
            {
                if (i != iRsize - 1)
                {
                    decialNum = k - i;    //计算小数点的位数
                }
            }
            else
            {
                x2[t++] = str[i] - '0';
            }
        }
        else
        {
            if (!label)
            {
                continue;
            }
            else
            {
                x2[t++] = 0;
            }
        }
    }
   
    return decialNum;
}

//大数加法
int  BigNumAdd(int *buf, int q, int ilen)
{
    int j = 0;    //进位
    int i;
    int k;

    for (i=q, k=0; k<ilen; k++, i++)
    {
        int tmp;

        tmp = result[i] + buf[k] + j;  //从个位开始,模拟手算
        result[i] = tmp % 10;
        j = tmp / 10;
    }

    if (j)
    {
        result[i] += j;
        i++;
    }

    return i;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值