雙向鏈表求高精度PI值
描述
限制使用雙向鏈表作存儲結構,請根據用戶輸入的一個整數(該整數表示精確到小數點後的位數,可能要求精確到小數點後500位),高精度計算PI值。可以利用反三角函數冪級展開式來進行計算:
輸入
輸入的一個正整數n
輸出
輸出PI的值,精確到小數點後n位,最後輸出一個回車。
輸入樣例
5
輸出樣例
3.14159
#include<stdlib.h>
#include<iostream>
#include<cstdio>
using namespace std;
typedef struct Node{
int data;
struct Node* pre;
struct Node* next;
}LNode,*LinkList;
void Print_List(LinkList lis){
LinkList p = lis;
cout<<"linklist:";
while(p){
cout<<p->data<<" ";
p = p->next;
}
cout<<endl;
}
void Create(LinkList p){
p->data = 0;
p->pre = NULL;
p->next = NULL;
}
void Mul(LinkList R,int top){
LinkList tail=R;
while(tail->next){
tail = tail->next;
}
int carry = 0;
while(tail->pre!=R){
int product = tail->data*top;
tail->data = product%10 + carry;
carry = product/10;
tail = tail->pre;
}
tail->data = tail->data*top + carry;
}
void Div(LinkList R, int bottom){
LinkList p = R->next;
int borrow = 0;
int n = 2000;
while((borrow||(p)!=NULL)&&n){
int dividend = borrow*10+p->data;
p->data = dividend/bottom;
borrow = dividend%bottom;
if(borrow&&!(p->next)){
p->next = (LinkList)malloc(sizeof(LNode));
p->next->pre = p;p->next->data = 0;p->next->next = NULL;
}
p = p->next;
--n;
}
}
void Sum(LinkList R,LinkList sum){
LinkList p = R->next;
LinkList q = sum->next;
LinkList pre_q;
int carry = 0;
int n = 2000;
while((p||q)&&n){
int he = (p?p->data:0) + (q?q->data:0);
if(!q){
q = (LinkList)malloc(sizeof(LNode));
q->data = 0;
q->next = NULL;
q->pre = pre_q;
}
q->data = he%10;
carry = he/10;
q->pre->data +=carry;
pre_q = q;
if(q){
if(p&&p->next&&!(q->next)){
q->next = (LinkList)malloc(sizeof(LNode));
q->next->pre = q;q->next->data = 0;q->next->next = NULL;
}
q = q->next;
}
if(p){
p = p->next;
}
--n;
}
}
int main()
{
//freopen("in.txt","r",stdin);
LinkList sum,R; int n;
cin>>n;
sum = (LinkList)malloc(sizeof(LNode));
R = (LinkList)malloc(sizeof(LNode));
Create(sum);Create(R);
sum->next = (LinkList)malloc(sizeof(LNode));
sum->next->data = 3;
sum->next->pre = sum;
sum->next->next = NULL;
R->next = (LinkList)malloc(sizeof(LNode));
R->next->data = 3;
R->next->pre = R;
R->next->next = NULL;
int s = 1;
while(s<2000){
int top = (2*s-1)*(2*s-1);
int bottom = 8*s*(2*s+1);
Mul(R,top);
Div(R,bottom);
Sum(R,sum);
s++;
}
if(n==0){
cout<<3<<endl;
}
else{
sum = sum->next;
cout<<sum->data<<".";
for(int i=0;i<n;i++){
if(!sum->next)break;
cout<<sum->next->data<<"";
sum = sum->next;
}
cout<<endl;
}
return 0;
}
代碼是C風格的,
1. 結構體struct用typedef來定義,而C++不需要,
2. 用malloc分配內存,而C++用new
3. 用NULL表示空指針,而C++使用nullptr
用arcsin進行的級數推導我沒有管,因爲重點不是數學。級數的每一項都和前面一項有關係。所以用一個係數去乘R,得到一個新的R。然後把這一系列R累加起來。代碼中的top和bottom分別表示係數的分子和分母。
注意事項:
鏈表的下一個節點爲空的時候,要注意用malloc去開闢一個新的。