求高精度幂
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。
现在要你解决的问题是:对一个实数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;
}
/************************************************************************************/