题目要求

  • 限制使用双向链表作存储结构,请根据用户输入的一个整数(该整数表示精确到小数点后的位数,可能要求精确到小数点后500位),高精度计算PI值。可以利用反三角函数幂级展开式来进行计算。
  • 输入5
  • 输出3.14159

思路分析

  • 反三角函数幂级展开式在这里插入图片描述
  • 由公式可以看出,只要计算出来每一个R(n)的值再相加取二倍就可以得到Π的值。
  • 经过推算,要是令R(1)=2,只需要将每个R(n),相加即可。
  • 因为,要求精度最高达到小数点后500位,所以我们不能使用已有的数据类型进行计算。这里我们使用双链表构造一个满足我们需求的足够长的数。
  • 对双链表组成的数用模拟手算的方法进行大数运算即可。
  • 根据题目具体情况,我们链表的第一个节点存储的是整数部分。

完整程序

#include <stdio.h>
#include <stdlib.h>
typedef struct node{
 int date;
 struct node* pre;
 struct node* next;
}node,*pnode; 
void insert(pnode list,int date){
//尾插法向链表中添加元素 
 pnode p = list;
 if(p==NULL){
  return; 
 }
 else{
  while(p->next){
   p = p -> next;
  }
   pnode pnew=(pnode)malloc(sizeof(node));
   pnew -> date = date;
   p -> next = pnew;
   pnew-> pre =p;
   pnew -> next = NULL;  
 } 
} 
void tranverselist(pnode list,int n){
//遍历链表并输出指定位数的小数 
 pnode p = list; 
 p=p->next;
 printf("%d.",p->date);
 int i;
 p=p->next;
 for(i=0;i<n;i++){
  printf("%d",p->date);
  if(p->next){
   p=p->next;
  }
 }
 printf("\n"); 
}
int main()
{
 pnode num;//num为每次相加的 R(n); 
 pnode sum;//sum最终的值约等于 Π;
 num=(pnode)malloc(sizeof(node));
 sum=(pnode)malloc(sizeof(node));
 num -> pre = NULL;
 sum -> pre = NULL;
 num -> next = NULL;
 sum -> next = NULL; 
 //n为题目要求输出的的Π的小数位数; 
 int n;
 scanf("%d",&n); 
 //给链表补够600位来进行计算,因为我的精度要达到500 
 int i; 
 for(i=0;i<600;i++){
  insert(num,0);
  insert(sum,0);
 }
 //p1,p2为指向两个链表的指针 
 pnode p1 = num -> next;
 pnode p2 = sum -> next;
  //使两个链表除头节点外第一个节点的数据为2,计算直接从R2开始计算,简化了计算 
 p1->date=2;
 p2->date=2;
  //指向num,和sum的尾节点
 while(p1->next){
  p1=p1->next;
 } 
 pnode numtail = p1;
 while(p2->next){
  p2=p2->next;
 }
 pnode sumtail = p2;
 //开始运算; 
 int temp = 0;//计算过程中产生的临时数据 
 int ret = 0; //计算过程中产生的借位or进位
 int t;//计算时有规律出现的除数 (2n+1)
 for(i=1,t=3;i<10000;i++,t=t+2){//根据数学的知识,算的次数越多越精确 
   //i同时承担计数和做乘数的任务 
   //先计算乘法(即公式中R(n)*n) 
   pnode p3 = numtail;
   ret=0;
   while(p3) { 
    temp = p3 -> date * i + ret;
    p3 -> date = temp%10;
    ret = temp/10;
    p3 = p3 -> pre;
   }   
   ret = 0;
   p3 = num -> next;
   //计算除法 (即公式中的R(n)*n/(2*n+1))
   while(p3){
     temp = p3 -> date + ret*10;
     ret = temp % t;
    p3 -> date = temp/t;
    p3=p3->next; 
   }  
   ret = 0;
   pnode  p4 = sumtail;
   p3 = numtail;
   //将得到的R(n)的值加入到结果中 
   while(p3&&p4){
    temp = p3 -> date + p4->date +ret ;
    ret = temp/10;
    p4->date=temp%10;
    p3=p3->pre;
    p4=p4->pre; 
   } 
 }  
 tranverselist(sum,n);  
 return 0; 
}

运行实例

在这里插入图片描述

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐