【算法】算法中的趣味数学(二)

求π的近似算法

  用两种方法编程求π的近似值。
  实例解析:
  1、用“正多边形逼近”的方法求出π的近似值
  我国的祖冲之就是用这种方法在世界上第一个得到精确度达小数点后第6位π值的。
  利用圆的内接正六边形边长等于半径特点将边数翻番,做出正十二边形,求出边长,重复这个过程,就可获得所需精度的π的近似值。
  假设单位圆的内接多边形的边长为2b,边数为i,则边数加倍后新的正多边形的边长为:
  周长为2ix (其中i为加倍前的正多边形的边数)
  2、利用随机数法求π的近似值
  基本思路是:在一个单位边长的正方形中,以边长为半径,以一个顶点为圆心,在正方形上做四分之一圆。随机向正方形内扔点,若落入四分之一圆内则计数。重复向正方形内扔足够多的点,将落入四分之一圆内的计数除以总的点数,其值就是π值四分之一的近似值。
  程序如下:
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
#define N 30000
int main()
{
    double e = 1.0, b = 0.5, c, d; //e为边长,b为边长的一半
    long int i;                       //i: 正多边形边数
    float x, y;
    int c2 = 0, d2 = 0;
    puts("\n >> Result of Regular Polygon Approximating:");
    for(i = 6;    ; i *= 2)
    {          //正多边形边数加倍
        d = 1.0 - sqrt(1.0 - b*b);   
        b = 0.5 * sqrt(b*b + d*d);  //b为新多边形边长的一半
        if(2*i*2*b – i*e < 1e-15)
            break;                      //精度达1e-15则停止计算
            e = 2*b;                     //保存新多边形的边长
    }
    printf("-----------------------------------------\n");
    /*以下输出π值和正多边形的边数*/
    printf(">>pi=%.15lf\n",2*i*b);
    printf(">>The number of edges of required polygon:%ld\n",i);
    printf("-----------------------------------------\n");
    randomize();
    while(c2++ <= N)
    {
        x = random(101);      //x:坐标。
        y = random(101);      //y:坐标。
        if(x*x + y*y <= 10000)   //判断点是否落在圆内
            d2++;
    }
    puts("\n >> Result of Random Number Method:");
    printf("----------------------------------------\n");
    printf(" >> pi=%f\n",4.*d2/N);    //输出求出的π值
    printf("----------------------------------------\n");
    puts("\n Press any key to quit...");
    getch();
    return 0;
}


角谷猜想
  日本一位学生发现一个奇妙的“定理”,请角谷教授证明,而教授无能为力,于是产生角谷猜想。猜想的内容是:任意给一个自然数,若为偶数则除以2,若为奇数则乘3加1,得到一个新的自然数,然后按照上面的法则继续演算,若干次后得到的结果必然为1。请编程验证。
  实例解析:
  题目给出的处理过程很清楚,直接进行验证即可。
  程序如下:
#include <stdio.h>
int main()
{
    int n, count = 0;
    printf(">>Please input a number to verify(0 to quit):");
    scanf("%d",&n);      //输入任一整数
    while(n != 0)
    {
        printf(">>------Results of verification:-------\n");
        do
        {
            if(n % 2)
            {
                n = n*3 + 1;           //若为奇数,n乘3加1
                printf(">>Step No.%d: %d*3+1=%d\n",++count,(n-1)/3,n);
            }
            else
            {
                n /= 2;               //若为偶数n除以2
                printf(">>Step No.%d: %d/2=%d\n",++count,2*n,n);
            }
        }while(n != 1);             //n不等于1则继续以上过程
        printf(">> -----------------------  ----------\n");
        printf(">>Please input a number to verify(0 to quit):");
        scanf("%d",&n);      //输入任一整数
    }
    puts("\n Press any key to quit...");
    getch();
    return 0;
}


四方定量
  数论中著名的“四方定理”讲的是:所有自然数至多只要用4个数的平方和就可以表示,请编程验证此定理。
  实例解析:
  对4个变量采用穷举试探的方法进行计算,满足要求时输出计算结果。
  程序如下:
#include <stdio.h>
void verify_four_squares(int number)
{
    int i,j,k,n;
    for(i = 1; i < number/2; i++)  //穷举法。试探i,j,k,n的不同值
        for(j = 0; j < i; j++)
            for(k = 0; k < j; k++)
                for(n = 0; n < k; n++)
                    if(number == i*i + j*j + k*k + n*n)
                    {
                        printf(">>%d=%d*%d+%d*%d+%d*%d+%d*%d\n",
                        number,i,i,j,j,k,k,n,n);
                        return;
                    }
}
int main()
{
    int number = 1;
    while(number != 0)
    {
        printf(">>Please input a number to verify(0 to quit):");
        scanf("%d",&number);      //输入任一整数
        if(number == 0)
            break;
        printf(">>------Results of verification: ----\n");
        verify_four_squares(number);
        printf(">>-----------------------------------\n");
    }
    puts("\n Press any key to quit...");
    getch();
    return 0;
}


卡布列克常数
    任意一个4位数,只要他们各个位上的数字是不完全相同的,就有如下规律:
  将组成该4位数的4个数字由大到小排列,形成由这4个数字构成的最大的4位数;
  将组成该4位数的4个数字由小到大排列,形成由这4个数字构成的最小的4位(如果4位数中含有0,则得到的数不足4位);
  求两个数的差,得到一个新的4位数(高位零保留)
  重复以上过程,最后得到的结果是6174,这个数被称为卡布列克数。请编程验证卡布列克数。
  实例解析:
   题目给出的处理过程很清楚,可按题目叙述直接进行验证。
   程序如下:
#include <stdio.h>
void vr6174(int);
void parse_sort(int num, int *each);
void max_min(int *each, int *max, int *min);
void parse_sort(int num, int *each);
int count = 0;
int main()
{
    int n = 1;
    while(n != 0)
    {
        printf(">>Please input a 4-digit number to verify(0 to quit): ");
        scanf("%d",&n);      //输入任一整数
        if(n == 0)
            break;
        printf(">>-----Results of verification: ------\n");
        count = 0;
        vr6174(n);           //调用函数进行验证
        printf(">> ----------------------------------\n");
    }
    puts("\n Press any key to quit...");
    getch();
    return 0;
}
void vr6174(int num)
{
    int each[4], max, min;
    if(num != 6174 && num)
    { //若不等于6174且不等于0则进行运算
    parse_sort(num,each);        //将整数分解,数字存入each数组中
    max_min(each,&max,&min);    //求数字组成的最大值和最小值    
    num = max - min;              //求最大值和最小值的差
    printf(">> Step No.%d:  %d-%d=%d\n",++count,max,min,num); //输出该步计算过程
    vr6174(num);         //递归调用自身继续进行卡布列克运算
    }
}
void parse_sort(int num,int *each)
{
    int i,*j,*k,temp;
    for(i = 0; i <= 4; i++)
    {        //将NUM分解为数字
        j = each + 3 - i;
        *j = num%10;
        num /= 10;
    }
    for(i = 0; i < 3; i++)     //对各数字从小到大进行排序
    for(j=each,k=each+1; j < each+3-i; j++,k++)
        if(*j > *k)
        {
            temp = *j;
            *j = *k;
            *k = temp;
        }
    return;
}
//下面函数将分解的数字还原为最大整数和最小整数
void max_min(int *each, int *max, int *min)
{
    int *i;
    *min = 0;
    for(i = each; i < each+4; i++)     //还原为最小的整数
        *min = *min * 10 + *i;
    *max = 0;
    for(i = each+3; i >= each; i--)    //还原为最大的整数
        *max = *max * 10 + *i;
    return;
}

本文出自 “成鹏致远” 博客,请务必保留此出处http://infohacker.blog.51cto.com/6751239/1171361

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验一 线性表及其应用 一、 实验目的和要求 1、掌握线性表的插入、删除、查找等基本操作设计实现 2、学习利用线性表提供的接口去求解实际问题 3、熟悉线性表的的存储方法 、 实验内容和原理 1、实验内容:设计一个一元多项式的简单计算器,其基本功能有①输入并建立多项式;②输出多项式;③多项式相加。可利用单链表或单循环链表实现之。 2、实验原理:以线性表来描述一元多项式存储结构采用单链表每个结点存储多项式一项系数指数,建立单链表指数高的结点列于指数低的 结点之后,即线性表的元素按指数递增有序排列。 三、 实验环境 Visual C++ 6.0 及PC机 四、 算法描述及实验步骤 思想算法: 以线性表来描述一元多项式存储结构采用单链表每个结点存储多项式一项系数指数,建立单链表指数高的结点列于指数低的结点之后,即线性表的元素按指数递增有序排列。 例如构造两个多项式ha: 5X3+4X2+3X+2 hb: X2+X+1 多项式加法:定义指针p,q分别指向ha,hb i.p->exp==q->exp ,r->coef=p->coef+q->coef,pa,pb下移; ii.p->expexp ,r->coef=q->coef;r->exp=q->exp;,q下移 iii.pa->exp>pb->exp, r->exp=p->exp;r->coef=p->coef;,p下移 iv.p!=NULL,pb==NULL.相当于iii. V.q==NULL,pb!=NULL.相当于ii. 其流程图如下: 多项式乘法:定义指针fp,gp分别指向f,g 1.将两多项式最大指数相加并赋于maxp,并置g 2.用for循环求指数等于maxp时相乘系数 3. (fp!=NULL)&&(gp!=NULL), p=fp->exp+gp->exp 1.p>maxp, fp=fp->next; 2. pnext; 3.p=maxp, x+=fp->coef*gp->coef; fp=fp->next;gp=gp->next; 五、 实验结果 1.分别输入两个多项式: 5X3+4X2+3X+2 和X2+X+1,然后输出结果如下: 2.分别输入两个多项式:6X4+4X2+2和5X+6,然后输出结果如下: 六、 总结 此次上机实验应用了线性表实现了一次实际操作,完成了一个一元多项式的简单计算器,不仅对此次编译程序的算法思想有了新的认识,还让我深刻的体会到了线性表的重要性以及其应用的方便,并且对指针加深了映象,应用了书本算法思想,对我以后的编译以及完成新的程序有很大的帮助。 附录: 1.建立多项式列表代码如下: mulpoly *creatpoly()/*建立多项式列表*/ {mulpoly *head,*r,*s;/*设间变量*/ int m,n; head=(mulpoly *)malloc(sizeof(mulpoly));/*头结点申请空间*/ printf("\ninput coef and exp:\n"); scanf("%d%d",&n,&m);/*输入多项式系数指数*/ r=head;/*尾指针指向头指针*/ while(n!=0)/*将输入的多项式存放在S*/ {s=(mulpoly*)malloc(sizeof(mulpoly)); s->coef=n; s->exp=m; r->next=s; r=s; /*printf("input coef and exp:\n");*/ scanf("%d%d",&n,&m);/*再次输入多项式系数指数*/ } r->next=NULL;/*将尾指针置空*/ head=head->next;/*将head哑结点向前跑一个结点,使其不为空*/ return (head);/*返回多项式*/ } 2.两个多项式相加代码如下: mulpoly *polyadd(mulpoly *ha,mulpoly *hb)/*两个多项式相加*/ {mulpoly *hc,*p,*q,*s,*r;/*声明结构体型*/ int x; p=ha; q=hb; hc=(mulpoly *)malloc(sizeof(mulpoly));/*申请结点空间*/ s=hc; while((p!=NULL)&&(q!=NULL))/*两多项式不为空*/

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值