编程能力提高-----循环的设计技巧(for、while)

  循环是程序设计中接触最多code。在进行数值计算的时候,循环往往是用来做累加或累乘的。累加和累乘都有通用的数学模型: Sn=Sn1+An Tn=Tn1An 。根据这两个数学模型,很容易构造出循环体。


例1:实现一个函数,求1+2+3+…+100的和。

int sum (int n)
{
    int s=0;
    for(int i=1;i<=n;i++)
        s=s+i;               //累和,超级简单。
    return s;
}

例2:设计求 n! n 为正整数)的算法。

long long int fun (int n)
{
    long long int f=1;
    for(int i=1;i<=n;i++)
        f=f*i;               //累积,超级简单。
    return f;
}

但在编程中,问题往往既涉及累加式又涉及到累乘式。如下面这个题目:

例3:设计求1/1!1/3!+1/5!1/7!+...+(1)n+1/(2n1)! n 为正整数)的算法。

分析问题:
首先,数学模型为:Sn=Sn1+(1)n+1/(2n1)!
其次,累加的对象是一个累积的结果。
所以,初学者很容易想到利用二重循环实现该算法。

int main()
{
    int i,j,n,sign=1;      //i、j为循环控制变量,n为问题规模
    float s=1,t=1;         //s累和,t累积
    scanf("%d",&n);
    for(i=2;i<=n;i++)
    {
        t=1;
        for(j=1;j<=2*i-1;j++)
            t*=j;
        sign=1;
        for(j=1;j<=i+1;j++)
            sign=sign*(-1);
        s=s+sign/t;
    }
    printf("sum=%d",s);
}

  对以上算法分析,是正确的,但是时间复杂度是 O(n2) ,效率低。因为在内循环中求出 7! 后,再去求 9! 时,没必要再从 1 去累乘到9,只需充分利用前一次的结果,用 7!89 即可求得 9! 。所以数学模型修正为: An=An11/((2n2)(2n1)) 。另外 sign=sign(1); 总共也要执行 n(n1)/2 次乘法操作,这也是没必要的,用赋值运算效率更高, sign=sign;

数学模型2: Sn=Sn1+(1)n+1An An=An11/((2n2)(2n1))

int main()
{
    int i,n,sign=1;        //i为循环控制变量,n为问题规模
    float s=1,t=1;         //s累和,t累积
    scanf("%d",&n);
    for(i=2;i<=n;i++)
    {
        sign=-sign;
        t=t*(2*i-2)*(2*i-1);        
        s=s+sign/t;
    }
    printf("sum=%d",s);
}

  该算法的时间复杂度为 O(n) 。由此可见,构造的循环不变式不同时,他们的效率也不同。对于比较难的问题,可以用“自顶向下”的设计方法,改变数学模型。

例4:设计求 sin(x)=xx3/3!+x5/5!x7/7!...... 的算法。

/*sinx=x-x^3/3!+x^5/5-x^7/7!...*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
    int i=1,sign=1;
    float x,t,fac=1,sinx=0;
    scanf("%f",&x);
    t=x;
    do
    {
        sinx+=sign*t/fac;
        t=t*x*x;                   //分子t初值为x
        fac=fac*(i+1)*(i+2);       //分母fac初值为1
        i+=2;
        sign=-sign;
    }while(fabs(t/fac)>=1e-7);
    printf("%f\n",sinx);
    return 0;
}

结果

算法分析:该算法在 x 的值较小时,计算的结果比较准确。但x=100等比较大的值时,误差较大。需要进一步改进。。。


参考资料:《算法设计与分析》   第二版   吕国英
转载请注明出处:http://blog.csdn.net/so_geili/article/details/71436430

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值