數據結構:高精度PI值(雙向鏈表)

雙向鏈表求高精度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去開闢一個新的。

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章