Description
限制使用双向链表作存储结构,请根据用户输入的一个整数(该整数表示精确到小数点后的位数,可能要求精确到小数点后500位),高精度计算PI值。可以利用反三角函数幂级展开式来进行计算。
Input
输入的一个正整数n
Output
输出PI的值,精确到小数点后n位,最后输出一个回车。
Sample Input
5
Sample Output
3.14159
用到iostream,stdlib.h
using namespace std;
typedef struct tagNODE
{
int date;
struct tagNODE *pre;
struct tagNODE *next;
}Lnode,*Linklist;
void createlink(Linklist *);
int main()//思路原理:R(n+1)=R(n)(n/2*n+1); R(1)=1 ; sum=pi=2[R(1)+…R(∞)];
{
Linklist num,sum;//分别是储存数字的结点和储存最终答案的结点
num=(Linklist)malloc(sizeof(Lnode));
sum=(Linklist)malloc(sizeof(Lnode));
Linklist p,q;//流动结点
int n;//计算精度
cin>>n;
createlink(&num);
createlink(&sum);
num->next->date=2;//整数部分初始为2
sum->next->date=2;//初始和(在这里有个point,公式里初始为1,结果和要乘以二才为pi值;而如果初始为2的话,最后结果和就是pi值)
p=num->pre;
int temp=0,ret=0;//分别是暂时数和进位(or借位)
int i;
for(i=1;i<10000;i++)//足够多的跑,满足足够的精度要求
{
p=num->pre;
while(p!=num)//乘法(从第五百位小数遍历到整数部分)
{
temp=(p->date*i+ret);
p->date=temp%10;
ret=temp/10;
p=p->pre;
}
ret=0;
p=num->next;
while(p!=num)//除法(从整数部分遍历到第五百位小数)
{
temp=(ret*10+p->date);
p->date=temp/(2*i+1);
ret=temp%(2*i+1);
p=p->next;
}
ret=0;
p=num->pre;
q=sum->pre;
while(p!=num)//加合即取合部分(从第五百位开始求和,这样方便进位)
{
temp=ret+p->date+q->date;
q->date=temp%10;
ret=temp/10;
p=p->pre;
q=q->pre;
}
}
q=sum->next->next;//从小数的地方输出
cout<<3<<'.';
while(n)
{
cout<<q->date;
q=q->next;
n--;
}
return 0;
}
void createlink(Linklist *l)//我们要建立一个双向并且头尾相连的链表
{
Linklist p=(*l),s;
int i;
for(i=0;i<=1000;i++)//这里需要注意的是,你算的精度(分配的空间)一定要比你想要的精度大一点:比如这里我要500,我不妨分配个1000个。
{
s=(Linklist)malloc(sizeof(Lnode));
s->date=0;
s->pre=p;
p->next=s;
s->next=(*l);
(*l)->pre=s;
p=p->next;
}
}