高精度计算PI值实验

前言:此文章用于高精度计算pi值,详细介绍了函数代码实现,可能比较繁琐,只需要代码的可以 翻到文末完整代码处,另外计算pi值的函数中会用到较多高数方面知识,如果不懂就得劳烦大家自行查阅相关资料。

一、需求分析

1、输入的形式和输入值的范围:输入一个正整数n,表示小数点后精确的位数,小于500

2、输出的形式:输出PI值,精确到小数点后n位,最后还要输出一个回车

3、程序所能达到的功能:高精度计算PI的值,并将其按位储存在一个双链表中

4、测试数据:

二、概要设计

为了实现上述操作,应以双向链表为存储结构。

1.基本操作:

void Create() 创建双链表,初始化值全部为0;

void he()    若链表存在,实现将两个链表对应项相加并储存到第一个链表中(注意进位)

void cheng()  若链表存在,实现将链表每位乘以个x并保存回去并注意进位

void chu()    若链表存在,实现将链表每一位对x的余数乘10加到本位

DLinkList pi()  实现计算高精度计算pi值

void show() 实现将链表的前n位输出,并按要求在最后输出一个换行符

2.本程序包含三个模块:

(1)主程序模块;

(2)构造链表并初始化模块;

(3)计算pi并输出模块;

(4)模块调用图:

主程序模块

构造链表并初始化模块

计算pi并输出模块

{

调用了和函数,积函数,商函数(具体作用见1)

}

最后调用show函数进行输出模块

 (三) 详细设计

1.元素类型,结点类型和指针类型:

typedef struct DNode

{

    int data;

    struct DNode* next;

    struct DNode* pre;

}DNode, * DLinkList;      

2.每个模块的分析:

(1)主程序模块:

int main()

{

    int n;

    scanf_s("%d", &n);

    DLinkList l, t;

    Create(&l, 999);                       

    Create(&t, 999);

    l=pi(l, t);

    printf("3.");

    show(l, n);                            

    return 0;

}

(2)构造链表并初始化模块;

void Create(DLinkList* L, int n)

{

    DLinkList s;

    *L = (DLinkList)malloc(sizeof(DNode));          

    (*L)->pre = (*L)->next = NULL;                    

    for (; n > 0; n--) {                                

        s = (DLinkList)malloc(sizeof(DNode));       

        s->data = 0;                                

        s->next = (*L)->next;

        if ((*L)->next != NULL) {                     

            (*L)->next->pre = s;

        }

        (*L)->next = s;                            

        s->pre = *L;

    }

}                      //创建初值为0的双链表

(3)计算pi并输出模块

DLinkList pi(DLinkList l, DLinkList t ) {

    t->next->data = 5;                           

    he(l, t);

    int  i, a, b;

    for (i = 1; i < 5000; i++) {                          

        a = (2 * i - 1) * (2 * i - 1);

        b = 8 * i * (2 * i + 1);

        cheng(t, a);

        chu(t, b);

        he(l, t);

    }             //泰勒展开,中间用到了递归(重要的pi值计算算法)

    cheng(l, 6);

    return l;

}

3.计算pi中用到的函数

  a.和函数 

 void he(DLinkList l, DLinkList t)

{

    DLinkList p, q;

    int a = 0;

    p = l;

    q = t;

    while (p->next != NULL) {                         

        p->next->data = p->next->data + q->next->data;

        p = p->next;

        q = q->next;

    }

    while (p->pre != NULL) {                         

        p->data += a;

        a = p->data / 10;

        p->data %= 10;

        p = p->pre;

    }

}                 //将两个链表的元素对应项加并保存到第一个链表里,还要注意进位

   b.积函数

   void cheng(DLinkList t, int x)

{

    DLinkList p;

    int a = 0;

    p = t;

    while (p->next != NULL) {                         

        p->next->data *= x;

        p = p->next;

    }

    while (p->pre != NULL) {                         

        p->data += a;

        a = p->data / 10;

        p->data %= 10;

        p = p->pre;

    }

}                         //将链表里每个元素乘以x并保存回去,注意进位

     c.商函数

void chu(DLinkList t, int x)

{

    DLinkList p;

    int a = 0;

    p = t->next;

    while (p != NULL) {

        p->data += a * 10;                          

        a = p->data % x;

        p->data /= x;

        p = p->next;

    }

}                       //将链表每一位对x的余数乘10加到本位

(4)函数调用关系图

main()

{

void Create()

DLinkList pi()

{

void he()

void cheng()

void chu()

}

void show()

}

3.完整的程序:

#include <stdio.h>
#include <stdlib.h>

typedef struct DNode
{
    int data;
    struct DNode* next;
    struct DNode* pre;
}DNode, * DLinkList;

void Create(DLinkList* L, int n)
{
    DLinkList s;
    *L = (DLinkList)malloc(sizeof(DNode));          
    (*L)->pre = (*L)->next = NULL;                    
    for (; n > 0; n--) {                                
        s = (DLinkList)malloc(sizeof(DNode));       
        s->data = 0;                                
        s->next = (*L)->next;
        if ((*L)->next != NULL) {                     
            (*L)->next->pre = s;
        }
        (*L)->next = s;                            
        s->pre = *L;
    }
}

void show(DLinkList L, int n)
{
    DNode* p = L;
    int i = 0;
    while (p->next != NULL && i < n) {
        p = p->next;
        printf("%d", p->data);
        i++;
    }
    printf("\n");
}

void he(DLinkList l, DLinkList t)
{
    DLinkList p, q;
    int a = 0;
    p = l;
    q = t;
    while (p->next != NULL) {                         
        p->next->data = p->next->data + q->next->data;
        p = p->next;
        q = q->next;
    }
    while (p->pre != NULL) {                         
        p->data += a;
        a = p->data / 10;
        p->data %= 10;
        p = p->pre;
    }
}

void cheng(DLinkList t, int x)
{
    DLinkList p;
    int a = 0;
    p = t;
    while (p->next != NULL) {                         
        p->next->data *= x;
        p = p->next;
    }
    while (p->pre != NULL) {                         
        p->data += a;
        a = p->data / 10;
        p->data %= 10;
        p = p->pre;
    }
}

void chu(DLinkList t, int x)
{
    DLinkList p;
    int a = 0;
    p = t->next;
    while (p != NULL) {
        p->data += a * 10;                          
        a = p->data % x;
        p->data /= x;
        p = p->next;
    }
}


DLinkList pi(DLinkList l, DLinkList t ) {
    t->next->data = 5;                           
    he(l, t);
    int  i, a, b;
    for (i = 1; i < 5000; i++) {                          
        a = (2 * i - 1) * (2 * i - 1);
        b = 8 * i * (2 * i + 1);
        cheng(t, a);
        chu(t, b);
        he(l, t);
    }
    cheng(l, 6);
    return l;
}

int main()
{
    int n;
    scanf_s("%d", &n);
    DLinkList l, t;
    Create(&l, 999);                       
    Create(&t, 999);
    l=pi(l, t);
    printf("3.");
    show(l, n);                            
    return 0;
}

(四) 程序使用说明及测试结果

1.程序使用说明

(1)本程序的运行环境为VC6.0。

(2)输入想要输出的pi后保留位数

2.运行界面

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
通信原理软件实验 实验报告 班级: 姓名: 班内序号: 学号: 电话 : 北 京 邮 电 大 学 Beijing University of Posts and Telecommunications 【实验目的】 本实验是"通信原理"的一个组成部分。在本实验中我们使用的软件工具是MATLAB。 设计本实验的目的是希望你在以下几方面有所收获; 1 、会MATLAB软件的最基本运用。 MATLAB是一种很实用的数学软件,它易学易用。MATLAB对于许多的通信仿真类问题来 说是比较合适的。   2、了解计算机仿真的基本原理及方法,知道怎样通过仿真的方法去研究通信问题。 3、加深对通信原理课有关内容的理解。 【实验任务】 1、掌握matlab的基本操作及了解基本的仿真方法,分析运行范例程序。 2、按以下要求编制仿真程序并调试运行,其中第四项为可选内容 (1)绘出正弦信号波形及频谱 (2)单极性归零(RZ)波形及其功率谱,占空比为50% (3)升余弦滚降波形的眼图及其功率谱。滚降系数为0.5。发送码元取为0、2。 (4)最佳基带系统的Pe~Eb\No曲线,升余弦滚降系数a=0.5,取样的偏差是Ts/4。 (5)Pe~Eb\No,升余弦滚降系数a=0.5,取样时间无偏差,但信道是多径信道,C(f) =abs(1-0.5*exp(-j*2*pi*f*dt)),dt=Ts/2。 (6)仿真数字基带传输系统,包括输入、输出信号波形及其功率谱,眼图(升余弦滚降 系数a=0.5),Pe~Eb\No曲线,取样时间无偏差。 (7)自选题(部分相应系统、模拟调制、数字频带传输)。 【实验原理】 从数学的角度来看,信息从一地传送到另一地的整个过程或者其各个环节不外乎是一 些码或信号的变换过程。例如信源压缩编码、纠错编码、AMI编码、扰码等属于码层次上 的变换,而基带成形、滤波、调制等则是信号层次上的。码的变换是易于用软件来仿真 的。要仿真信号的变换,必须解决信号与信号系统在软件中表示的问题。 时域取样及频域取样 一般来说,任意信号是定义在时间区间上的连续函数,但所有计算机的CPU都只能按 指令周期离散运行,同时计算机也不能处理这样一个时间段。即计算机处理信号是离散运 行,有限域的。 对s(t)的解决方法:我们把按区间截短为,再对 ) (t s T 按时间间隔均匀取样得到个样 。仿真时我们用这个样集合来表示信号。这样,将会出现一系列新的问题,现在从频 域分析其频谱的变化。显然反映了仿真系统对信号波形的分辨率,越小则仿真的精确度越 高。据通信原理所学,信号被取样以后的频谱是频率的周期函数,其重将(-inf, inf)截短 为[-T/2,T/2],再将[-T/2,T/2]的信号均匀采样,采样点数为N=T/dt 1.采样信号xs (i)及其频谱Xs (ω) 若连续时间信号x(t)被数采卡DAQ中的采样器以等时间间隔T采样,则采样时刻0、T、 2T…所 取得信号x(t)的瞬时,就构成了连续信号x(t)的离散时间序列xs (i),i=0、1、2…如下 图所示。图一:连续信号与离散信号 当x(t)的频谱为X(ω)时,则xs (i)的频谱Xs (ω),如下图所示。 为保证不出现频率混叠失真,要求: H t 2 2 即 H f t 2 1 , 取 H f t B s = = 1 2 1 Bs定义为仿真系统的带宽。 从以上的推导可以看出:信号的时间采样间隔一定,则仿真信号的带宽也就相应定 了,反之仿真信号的带宽一定,则信号的时间采样间隔也就相应定了。 2对频谱S(f)的处理 将频域为无限域的频域信号S(f)截短为[-Bs,Bs]域的信号 ) ( f S s B ,再将带宽为[-Bs, Bs]的信号 ) ( f S s B 均匀采样,采样点数为Nf=2Bs/df。 为保证不出现时域波形重叠失真,要求 T f 1 , 取 T t = 1 , 即 f T = 1 从以上的推导可以看出:信号的频率采样间隔一定,则仿真信号的周期也就相应定 了,反之仿真信号的周期一定,则信号的频率采样间隔也就相应定了。 下面我们看看时域取样点数和频域取样点数的关系: 时域取样点数: f t N t T N f T t t = = = 1 , 1 得 带入 将 频域取样点数: f t N f B N t B f s f s = = = 1 , 2 2 1 得 带入 将 所以,时域取样点数与频域取样点数取相同,这样就可以保证连续时间信号及连续 频率信号均不出现重叠失真。 以上是防止重叠失真。 另外,为了提高仿真精度,要求提高取样点数N,其取为2的冪次, * , 2 , 1 , 0 , 2 = = k N k 为了处理上的方便,我们今后规定采样点数N为2的整幂。举例来说,假如设计要求的系统 带宽

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值