关于北大ACM1001题的一个答案

myme5261314 2009-04-27 09:21:41
求高精度幂
Time Limit: 500MS Memory Limit: 10000K
Total Submissions: 49678 Accepted: 11456

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

Sample Output

548815620517731830194541.899025343415715973535967221869852721
.00000005148554641076956121994511276767154838481760200726351203835429763013462401
43992025569.928573701266488041146654993318703707511666295476720493953024
29448126.764121021618164430206909037173276672
90429072743629540498.107596019456651774561044010001
1.126825030131969720661201

Source
East Central North America 1988

Translator
北京大学程序设计实习,Xie Di


下面是我在网上找到的一份答案


#include "stdafx.h"
#include <iostream>
using namespace std;
int n = 0,flag_i = 0,flag_j = 0,seal_x,seal_y,c,place_doc,digit,z,seal_store_active,seal_store_static,seal_digit,seal_record_a_n,doc_place = 0;
class number
{
private:
char a[10000];
int b[10000];
char d[10000];
public:
//************************initialize*****************************
number()
{
for(n = 0;n < 10000;n++)
{
b[n] = 0;
d[n] = 0;
}
};
//*************************input digit*******************************
int input_digit()
{
cin >> digit;
if(digit < 0 || digit > 25)return 0;
}
//*******************input a[]******************************
void get_a(){cin >> a;};
//*****************find doc place and remove it*************
int find_remove_doc()
{
for(n = 0;a[n] != '\0';n++)
{
if(a[n] == '.')
{
place_doc = n;
for(;a[n] != '\0';n++)
{
a[n] = a[n+1];
}
break;
}
}
if(n >= 6)return 0;
}
//*****************treansform a[] form char to int**********
void transform()
{
for(n = 0;a[n] != '\0';n++)
{
a[n] = a[n] - 48;
}
seal_store_active = n - 1;
seal_store_static = n - 1;
}
//*******************store a[] to d[] **************
void store()
{
for(n = 0;n <= seal_store_active;n++)
{
d[n] = a[n];
}
seal_record_a_n = n - 1;

}
//***********multiply a^n ********************************
void multiply()
{
flag_i = 0;
flag_j = 0;
seal_store_active = seal_store_static;
while(seal_store_active != -1)
{
for(n = seal_record_a_n;n != -1;n--,flag_i++)
{
b[flag_i] += d[seal_store_active] * a[n];
}
flag_j++;
c = flag_i;
flag_i = flag_j;
seal_store_active--;
}
flag_i = 0;

}
//**************deal with b[]*****************
void deal_with_b()
{
for(flag_j = 0; flag_j < 5;flag_j++)
{
if(b[c - 1] > 9)c = c + 1;
for(n = c - 1;n != -1;n--)
{
if(b[n] > 9)
{
b[n + 1] += b[n] / 10;
b[n] = b[n] % 10;
}
}
}
}


//****************** transfer *****************
void transfer()
{
flag_i = c - 1;
for(n = 0;n < c ;n++)
{
a[flag_i] = b[n];
flag_i--;
}
}

//******************** total program ***********
void program()
{
for(seal_digit = 0;seal_digit < digit - 1;seal_digit++)
{
multiply();
deal_with_b();
transfer();
if(seal_digit == digit - 2)break;
clean_b();
}
}


//******************** clean b[] ******************
void clean_b()
{
for(n = 0;n < c;n++)
{
b[n] = 0;
}
seal_record_a_n = c - 1;

}
//*********************remove the doc****************
int remove_doc()
{
if(place_doc == 0)return 1;
place_doc = seal_store_static - place_doc + 1;
for(seal_digit = 0;seal_digit < digit;seal_digit++)
{
doc_place += place_doc;
}
}

//*********************input the doc********************
void input_doc()
{
for(n = c;n != -1;n--)
{
b[n] = b[n - 1];
if(n == doc_place)
{
b[n] = '.';
break;
}
}
}
//********************determine b********
void determine_b()
{
for(n = 0;b[n] == 0;n++)
b[n] = 1000;
}
//****************cout b************************
void putout()
{
for(n = c;n != -1;n--)
{
if(b[n] == 1000)break;
if(b[n] == 46)
{

if(place_doc == 0)
{
break;
}
cout << ".";
continue;
}
cout << b[n];
}
}
//***********************main()******************************
};
int main()
{
for(;;)
{
number ob;
ob.get_a();
ob.input_digit();
ob.find_remove_doc();
ob.transform();
ob.store();
ob.program();
ob.remove_doc();
ob.input_doc();
ob.determine_b();
ob.putout();
cout << endl;
}
return 0;
}



这份答案我看了有两天了,但是始终不完全明白他的算法,大致的我了解到一点点,但是还是有很多疑问,对不起,我是C++新手,看这个程序看的我无从下手,有没有哪位能帮我理下思路,或者告诉我其中的关键算法,例如那个multiply函数部分,我就完全看不懂,还有,里面有很多变量,我光从名字上看也看不清楚到底是做什么用的。很惭愧啊,有没有关于如何看别人写的代码的技巧或者步骤的帖子或者资料之类的,如果有人知道,希望有人告诉我下,谢谢!
...全文
1036 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiatiandefengfree 2011-05-16
  • 打赏
  • 举报
回复
正好我也不懂
myme5261314 2009-04-30
  • 打赏
  • 举报
回复
不好意思。。。。。我第一次发帖。。。。分给错楼了。。。饿。。。真是的。。。。
测试菜鸟 2009-04-28
  • 打赏
  • 举报
回复
mark
xghuzd 2009-04-28
  • 打赏
  • 举报
回复
建议在看代码前,你要对代码的逻辑过程先了解.
它是干什么的? 它里面会有什么的运算过程?
myme5261314 2009-04-28
  • 打赏
  • 举报
回复
我差不多知道我找到的这个答案的难点在哪里了,就是模拟手算。。。。。3楼的程序我看看再说,谢谢大家的帮忙,这个论坛高手真多。。。(或者是我太菜鸟?)呵呵
alexhilton 2009-04-27
  • 打赏
  • 举报
回复
这道题有点水, 看上去是考高精度, 其实对高精度的要求不高, 一般模拟就可以了;
这题的变态之处在于它的数据特别变态:有如下几种:0010.00, 0010.0010, 000.0001等。
当年做的时候, 算法没有任何问题, 但就是过不了, 后来才发现是数据的问题!
firstdad 2009-04-27
  • 打赏
  • 举报
回复
细节问题
liao05050075 2009-04-27
  • 打赏
  • 举报
回复
或者你看看我这份。。
方法其实就是模拟手算,先用第二个数的一个数字乘以第一个数,然后保存,然后再乘一位,加起来再保存。

这题目的输出很麻烦。我改了两次输出才搞定的
下面是我的代码。


#include<stdio.h>
#include<string.h>

int main()
{
char s[7];
int n,lena,decp;
char b[500],c[500];
lab1: while(scanf("%s%d",s,&n)>0)
{
char a[500]={0};
if(!strcmp(s,"0.0000")) {printf("0\n");goto lab1;}
strrev(s);
int i=0,j=0;
while(s[i]=='0') i++;
while(i&&i<(int)strlen(s)+1)
s[j++]=s[i++];
i=0;
int len=strlen(s);
while(s[i]!='.') i++;
decp=i*n;
for(;i<=len;i++) s[i]=s[i+1];
len--;
for(i=0;i<len;i++) {s[i]-=48;a[i]=s[i];}
lena=len;
int k=0;

int t;
while(--n)
{
t=0;
int tmp=0;
for(j=0;j<500;j++) c[j]=0;
for(i=0;i<len;i++)
{ if(!s[i]) goto lab;
for(j=0;j<500;j++) b[j]=0;
tmp=0;
for(j=0;j<lena;j++)
{
b[j+t]=s[i]*a[j]+tmp;
tmp=0;
if(b[j+t]>9)
{
tmp=b[j+t]/10;
b[j+t]%=10;
}
}
if(tmp) b[j+t]=tmp;
for(k=t;k<=t+lena;k++)
{
c[k]+=b[k];
if(c[k]>9)
{
c[k+1]+=c[k]/10;
c[k]%=10;
}
}
while(c[k]>9)
{
c[k+1]+=c[k]/10;
c[k]%=10;
k++;
}
lab: t++;
}
j=0;
while(j<k) {a[j]=c[j];j++;}
lena=j;
}

//output
while(!a[lena]) lena--;
if(decp>lena)
{
printf(".");
for(i=decp-lena-1;i>0;i--) printf("0");
while(lena)
printf("%d",a[lena--]);
printf("%d\n",a[0]);
}
else
{
for(i=lena;i>=0;i--)
if(i==decp&&decp!=0) printf("%d.",a[i]);
else printf("%d",a[i]);
printf("\n");
}

}
return 0;
}



Paradin 2009-04-27
  • 打赏
  • 举报
回复
建议去搜索高精度计算的资料。网上很多的。
Paradin 2009-04-27
  • 打赏
  • 举报
回复
就是模拟手算。复杂度是n*n,如果没用分治的话。

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧