前言:此文章用于高精度计算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.运行界面