OJ_1001

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

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

Source

Translator

北京大学程序设计实习,Xie Di
 
 
============================================================================
真TMD佩服CSDN,如此XX用户的意愿。自己上传的资源自己都不能删除,真是服大发了!如果代码
写的有问题难道还非得误导那些下载的朋友们!下面的代码已经放在新浪爱问资料共享,地址
http://iask.sina.com.cn/u/ish ,没有上传工程文件,你可以随便用哪个版本的VC建一个就可以。
 
工程目录如下:
 
 
注:目前程序性能还达不到要求500MS,正在调试中。。。
/**************************************************************************************************/
//basecls.h
/*
运算实现的基类,不同的操作可以从此处派生出一个实现类
*/
#include <string>
using namespace std;
virtual class clsBaseAcl
{
public:
    virtual std::string Acl(const std::string strOp1, const std::string strOp2) = 0;
};

 
/*************************************************************************************************/
//acl.h
#include "basecls.h"

class clsAdd:public clsBaseAcl
{
public:
    std::string Acl(const std::string strOp1, const std::string strOp2);
};


class clsSub:public clsBaseAcl
{
public:
    std::string Acl(const std::string strOp1, const std::string strOp2);
};

class clsMultiply:public clsBaseAcl
{
public:
    std::string Acl(const std::string strOp1, const std::string strOp2);
 std::string AclEx(const std::string strOp1, const std::string strOp2);
};

std::string strAcl(const std::string strOp1, const std::string strOp2, int nBeforeOrAfter, int* pCarry);
/*
返回R的N次方
*/
std::string strRetRN(const std::string R, const short n);
void RemodePreZero(string& str);
void RemodeZero(string& str);

/*******************************************************************************************/
//acl.cpp
 
#include "acl.h"
char spliter = '.';
std::string clsAdd::Acl(const std::string strOp1, const std::string strOp2)
{
 int carry = 0;
    string str1(strOp1);
    string str2(strOp2);
 string strBefore1;
 string strBefore2;
 string strAfter1;
 string strAfter2;
 string strOut1;
 string strOut2;
    int npos1 = str1.find(spliter);
    if(string::npos == npos1)
    {
        str1 += ".0";
  npos1 = str1.length() - 2;
    }

    int npos2 = str2.find(spliter);
    if(string::npos == npos2)
    {
        str2 += ".0";
  npos2 = str2.length() - 2;
    }
    
 strBefore1 = str1.substr(0, npos1);
 strBefore2 = str2.substr(0, npos2);

 strAfter1 = str1.substr(npos1 + 1, str1.length() - npos1 - 1);
 strAfter2 = str2.substr(npos2 + 1, str2.length() - npos2 - 1);
 strOut1 = strAcl(strAfter1, strAfter2, 0, &carry);
 strOut2 = strAcl(strBefore1, strBefore2, 1, &carry);
 strOut1 =  strOut2 + "." + strOut1;
 
 //如果和的第0位还需要进位在加结果加1
 if (1 == carry)
 {
  strOut1 = "1" + strOut1;
 }
    return strOut1;
}

std::string clsSub::Acl(const std::string strOp1, const std::string strOp2)
{
    //return strOp1 + strOp2;
    return "sub";
}

std::string clsMultiply::Acl(const std::string strOp1, const std::string strOp2)
{
 clsAdd instAdd;
 string out;
 string retInt;
 string retDot;
 string strDot;
 int nInt = 0;
 int nDot = 0;
 int offset = 0;

 string s1(strOp1);
 int pos1 = strOp1.find(spliter);
 if (pos1 == string::npos)
 {
        s1 = s1 + ".0";
 }
 int pos = strOp2.find(spliter);
 if (pos != string::npos)
 {
  int nLastZero = strOp2.find_first_not_of('0', pos + 1);
  if (nLastZero != string::npos)
  {
   offset = nLastZero - pos;
   nDot = atoi(strOp2.substr(pos + 1, strOp2.length() -pos - 1).c_str());
   retDot = s1;
   for (int j = 1; j < nDot; ++j)
   {
    retDot = instAdd.Acl(retDot, s1);
   }
  
   int nDotPos = retDot.find(spliter);
   if(string::npos != nDotPos)
   {
    if (nDotPos > offset)
    {
     //20.5
                 retDot = retDot.substr(0, nDotPos-1) + "." + retDot.substr(nDotPos-1, retDot.length() - nDotPos+1);
     int nLastDotPos = retDot.find_last_of(".");
                 if(string::npos != nLastDotPos)
     {
                     retDot = retDot.substr(0, nLastDotPos) + retDot.substr(nLastDotPos + 1, retDot.length() - nLastDotPos - 1);
         retDot = "0" + retDot;
     }

    }
    else
    {
     retDot = retDot.substr(0, nDotPos) + retDot.substr(nDotPos + 1, retDot.length() - nDotPos - 1);
     string addzero(offset -nDotPos, '0');
     retDot = "0." + addzero + retDot;
    }
  
   }
  }
  else
  {
      retDot = "0.0";
  }

 }


 nInt = atoi(strOp2.substr(0, pos).c_str());
 retInt = s1;
 for (int i = 1; i < nInt; ++i)
 {
        retInt = instAdd.Acl(retInt, s1);
 }

    return instAdd.Acl(retInt, retDot);
}


std::string clsMultiply::AclEx(const std::string strOp1, const std::string strOp2)
{
 clsAdd instAdd;
 string out;
 int nDot1 = 0;
 int nDot2 = 0;
 int N2 = 0;
 int offset = 0;

 string s1(strOp1);
 int pos1 = strOp1.find(spliter);
 if (pos1 != string::npos)
 {
  nDot1 = s1.length() - pos1 - 1;
  s1 = s1.substr(0, pos1) + s1.substr(pos1 + 1, s1.length() - pos1 - 1); //去掉小数点
 }

 string s2(strOp2);
 int pos2 = strOp2.find(spliter);
 if (pos2 != string::npos)
 {
  nDot2 = s2.length() - pos2 - 1;
  s2 = s2.substr(0, pos2) + s2.substr(pos2 + 1, s2.length() - pos2 - 1);
 }

 N2 = atoi(s2.c_str());
    RemodePreZero(s1);
 out = s1;
 for (int i = 1; i < N2; ++i)
 {
        out = instAdd.Acl(out, s1);
 }

 RemodeZero(out);
 //加入小数点
 offset = nDot1 + nDot2;
 if (offset > 0)
 {
  if (offset < out.length())
  {
   out = out.substr(0, out.length() - offset) + "." + out.substr(out.length() - offset, offset);
  }
  else
  {
      string sz(offset - out.length(), '0');
      out = sz + out;
      out = out.substr(0, out.length() - offset) + "." + out.substr(out.length() - offset, offset);
  }
 }
 RemodeZero(out);

 if (0 == out.find(spliter))
 {
        out = "0" + out;
 }
    return (out);
}

std::string strAcl(const std::string strOp1, const std::string strOp2, int nBeforeOrAfter, int* pCarry)
{
    int dif = 0;
 int nStart = 0;
 int preCarry = 0;
 string str1;
 string str2;
 int tmp;
    int curr;
 string strOut;

 str1 = strOp1;
 str2 = strOp2;
 if(strOp1.length() < strOp2.length())
 {
  str1 = strOp2;
  str2 = strOp1;
 }

 nStart = str1.length() - 1;
 dif = str1.length() - str2.length();
 string strAddZero(dif, '0');

 if (1 == nBeforeOrAfter)
 {
        //小数点之前,在数字前面补0
  str2 = strAddZero + str2;
 } 
 else
 {
  //小数点之后,在数字后面补0
  str2 = str2 + strAddZero;
 }

 preCarry = *pCarry;
 while(nStart >= 0)
    {
        tmp = (str1[nStart]-'0') + (str2[nStart]-'0');
        tmp += preCarry; //当前数字+上一位的进位
        if(tmp >= 10)
        {
            curr = tmp%10;
            preCarry = 1;
        }
        else
        {
            curr = tmp;
            preCarry = 0;
        }
        nStart--;
  char p[32] = {0};
  sprintf(p, "%d", curr);
  string s = p;
  strOut = s + strOut;
    }
 *pCarry = preCarry;
 return strOut;
}

std::string strRetRN(const std::string R, const short n)
{
    string strOut;
 clsMultiply multi;
    if( R.length() <= 0)
 {
     return "para error";
 }
 
 if((n <= 0) || (n > 25))
 {
     return "para error";
 }

 strOut = R;
 for(int i = 1; i < n; ++i)
 {
     strOut = multi.AclEx(strOut, R);
 }

 return strOut;
}

//去掉前导0
void RemodePreZero(string& str)
{
 if (str.length() <= 0 )
 {
  return;
 }
 int dpos = str.find(spliter);
 if (string::npos == dpos)
 {
     //本身没有小数点%
     int pos = str.find_first_not_of('0');
  if (pos > 0)
  {
   str = str.substr(pos, str.length() - pos);
  }
 }
 else
 {
//   int pos = str.find_first_not_of('0', dpos + 1);
//   if ((pos > dpos) && (string::npos != pos))
//   {
//    str = str.substr(dpos - 1, str.length() - pos);
//   }
 
 }
}

//去掉多余的0
void RemodeZero(string& str)
{
 int nDotPos = -1;
 if (str.length() <= 0 )
 {
  return;
 }

 //如果小数点后全是0则去掉小数点后的0
 int pos = str.find(spliter);
 if (string::npos != pos)
 {
  int nFirstNotZero = -1;
        nFirstNotZero = str.find_last_not_of('0'); //小数点后最后一个不是0的字符位置
  if (nFirstNotZero == pos)
  {
    //走到这里说明小数点后都是0,去掉这些0和小数点
    str = str.substr(0, pos);
  }
  else if(nFirstNotZero > pos)
  {
             str = str.substr(0, nFirstNotZero+1);
  }

 }
 
}

/*********************************************************************************************/
//main.cpp
 
#include <iostream>
#include "acl.h"
#include <cassert>
using namespace std;

clsAdd add;
clsSub sub;
clsMultiply multi;
string a = "0.4321";
string b = "12";
string c = "00700";
string out;
//163.47 + 27.532 =191.002
int main()
{
    //cout << "Hello world!" << endl;
 //out = add.Acl(a,b);
 RemodePreZero(a);
 RemodeZero(a);

 RemodePreZero(b);
 RemodeZero(b);
 //out = multi.AclEx(a,b);
 //assert("16" == out);
 out = strRetRN(a,20);
 //cout << out << endl;
    //cout << sub.Acl(a,b)<< endl;
    //cout << multi.Acl(a,b)<< endl;
    return 0;
}

/************************************************************************************/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值