设计程序,实现高精度圆周率的计算和存储,使用线性表突破程序设计语言内置变量的数值和有效数字范围限制

一、使用线性表突破程序设计语言内置变量的数值和有效数字范围的限制,为了实现高精度圆周率的计算,先根据数学公式进行对PI高精度运算,如图1-1。根据这个数学公式 π2 = 0nn!2n+1‼ 即 Rn+1=Rn*n2n+1R1=1sum= π=2* n=1Rn 来计算PI值。首先先建立双链表,再对其初始化。根据其特性,实现了对大数的加法,乘法和除法,以此来完成对PI的高精度计算如图1-1,最后将PI的值储存到文件中如图1-2。

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

// 定义双链表节点结构体
typedef struct list
{
    int data;               // 节点数据域
    struct list *next;     // 指向下一个节点的指针
    struct list *pre;      // 指向前一个节点的指针
}list;

// 初始化双链表,返回链表头节点
list* Initlist()
{
    list *head;
    head = (list*)malloc(sizeof(list)); // 为头节点分配内存
    if (!head)
        exit(EXIT_FAILURE); // 如果内存分配失败,则退出程序
    else
        head->next = head->pre = head; // 初始化头节点的next和pre指针指向自己
    return head;
}

// 创建指定长度的双链表,返回链表头节点
list *Creatlist(list *head)
{
    list *p = head;
    for (int i = 0; i < 1000; i++) // 循环创建1000个节点
    {
        list *q = (list*)malloc(sizeof(list));
        if (!q)
            exit(EXIT_FAILURE); // 如果内存分配失败,则退出程序
        else
        {
            q->data = 0; // 将新节点q的数据域设置为0
            q->pre = p;  // 将新节点q的前置指针指向当前节点p
            p->next = q; // 将当前节点p的下一个节点指针指向新节点q
            q->next = head; // 将新节点q的下一个节点指针指向链表的头节点head,形成一个环形链表
            head->pre = q; // 将头节点head的前置指针指向新节点q,完成环形链表的构建
            p = p->next; // 将当前节点p移动到下一个节点,为下一次循环做准备
        }
    }
    return head;
}

void Save(int n) //存储PI
{
    FILE *fp = fopen("E:\\C语言的软件\\数据结构与算法\\1\\PI的存储.txt","w+");
    fprintf(fp,"%d",n);
    fclose(fp);
}

int main()
{
    int n;
    printf("请输入PI要精确到的位数\n");
    scanf("%d", &n); // 输入需要的小数位数

    list *number, *sum;
    list *p, *q, *x;

    number = Initlist(); // 初始化number链表
    sum = Initlist();    // 初始化sum链表

    number = Creatlist(number); // 创建number链表
    sum = Creatlist(sum);       // 创建sum链表

    number->next->data = 2; // number链表的第二位储存2,即2*R(1)=2
    sum->next->data = 2;   // sum链表的第二位也储存2

    int a = 0, b = 0; // 分别是用来暂时存储进位和余数

    for (int i = 1; i < 2000; i++) // 循环两千次,用于计算π的近似值
    {
        p = number->pre; // 开始大数乘法时从number链表的尾部开始

        while (p != number) //大于10则把10位的数字给b,个位数字放入data域中。
        {   //乘法运算
            a = p->data * i + b; // 计算当前位乘以i加上之前的进位
            p->data = a % 10; // 取个位数放入当前节点的data域
            b = a / 10; // 计算进位
            p = p->pre;  // 移动到前一个节点
        }

        b = 0; // 清空b,为除法做准备

        p = number->next; // 开始大数除法时从number链表的前部开始

        while (p != number) //若计算出的数字为自然数,则直接放入data域;若等于0,或为小数,则要计算余数并给b。
        {   //除法运算
            a = p->data + b * 10; // 计算当前位加上之前的余数乘以10
            p->data = a / (2 * i + 1); // 计算当前位的商,并放入当前节点的data域
            b = a % (2 * i + 1); // 计算余数
            p = p->next; // 移动到下一个节点
        }

        b = 0; // 清零b

        p = number->pre; // 开始大数加法时从number链表的尾部开始
        q = sum->pre;  // 从sum链表的尾部开始

        while (p != number) //大于10进位,并储存个位数,进位数字赋给b。
        {   // 加法计算
            a = p->data + q->data + b; // 计算当前位的和加上之前的进位
            q->data = a % 10; // 取个位数放入sum链表的当前节点的data域
            b = a / 10; // 计算进位
            p = p->pre; // 移动到number链表的前一个节点
            q = q->pre; // 移动到sum链表的前一个节点
        }
    }

    printf("3."); // 输出π的前缀"3."

    x = sum->next->next; // 从sum链表的第三个节点开始输出,即输出π的小数部分

    FILE *fp = fopen("E:\\C语言的软件\\数据结构与算法\\1\\PI的存储.txt","w+");
    fprintf(fp,"3.");
    for (int i = 0; i < n; i++) // 输出n位小数
    {
        fprintf(fp,"%d",x->data); //存储PI
        printf("%d", x->data); // 输出当前节点的data域的值
        x = x->next; // 移动到下一个节点
    }
    fclose(fp);
    return 0;
}

图1-1 实现PI的高精度的计算

图1-2 高精度PI的存储
  • 12
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值