学会思考程序

本文详细解析了一道关于计算1+2!+3!+...+20!的题目,从初版程序出发,逐步优化并修正了数据类型限制带来的问题。通过此过程,介绍了如何进行有效的程序调试和优化技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

求1+2!+3!+...+20!的值


原答案:

    int sum = 0;
    int p = 1;
    for (int i = 1; i <= 5; i++)
    {
        
    
        for (int j = 1; j <= i; j++)
        {
            p = p*j;
        }
        sum = sum+p;
    }
    printf("%d", sum);


很明显错误,只要代入几个数去计算一下,错误原因也很容易分析,没有清空p变量,这p变量一直剧增


修改答案:

    int n = 5;
    int sum = 0;
    int temp;		// 用temp替代p,为什么这里面变量要见文识意,这里是临时变量的意思

    for (int i = 1; i <= n; i++)
    {
        
    	temp = 1;

        for (int j = 1; j <= i; j++)
        {
            temp = temp*j;
        }
        sum = sum+temp;
    }
    printf("%d", sum);


然后代入计算,发现基本正确。但是从程序优化的思想去想,上面这个方案是否是最优的?

首先我们来看看一个嵌套循环带来了什么问题:

    int n = 2, count = 0;
    
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            printf("%d \n", ++count);
        }
    }

程序输出4个数:

1

2

3

4

如果这个时候我们改成n = 10,看看输出:

.......

直接成倍数增长!!更何况是如果20行,100行,所以我们每一个程序最基本的优化就是能不能减少循环的嵌套

这个时候我们分析这个题目简单的逻辑算法:

1+2!+3!  = 1 + 1*2 + 1*2*3

1+2!+3!+4!+5! = 1 + 1*2 + 1*2*3 + 1*2*3*4 + 1*2*3*4*5   可以看到有一段东西像sum一样一直迭代上去!


这样我们就可以写出这样的程序:

    int i, temp, sum = 0;

    temp = 1;

    for(i = 1; i <= 20; i++)

    {
        temp = temp*i;
        sum = sum + temp;
    }

    printf("sum=%d",sum);

(自行看懂这个程序哈,这个看不懂就要面壁思过~)

然后输入几个小的数字上去看看,3,5,6 ,手写笔算,发现,都正确,好像有点爽,但是我们输入20,答案:268040729

大多数的新人都会到这里为止,欧耶!感觉自己发现新大陆了,解决了一个世纪问题,成为编程界的明日之星

但是像我这样的老油条,会摇摇头,不对,哪里不对劲,敏感性地(这就相当于常话说的语感)加上一句,这一句会伴随你你的日后编程生涯

输出日志!我们把过程重要的值的输出来,那就可以追踪你的程序过程!那就随时跟踪你的变量是否达到你想要的!

这个时候我们看看会咋样?

    int i, temp, sum = 0;

    temp = 1;

    for(i = 1; i <= 20; i++)

    {

        temp = temp * i;

        sum = sum + temp;

        printf("pro is :%d \n", temp);
    }

    printf("sum=%d \n",sum);

结果:



这个时候,你应该擦擦眼睛,不对,画风有点不对。这TM怎么是负数啊!!计算机是不是小学都没有学好啊!正数相乘怎么来了一个负数!!


这时候有没有想起卢B说过忒装逼的一句话:不要迷信任何书,任何人,任何老师,任何所谓权威,你要相信的,只有编译器

计算机说什么就是什么!!!所以肯定是程序哪里出错了


此处应该是背着手,去庭院前吹吹风,听听扫地阿姨八卦,突然有了灵感,这个出错规律是越来来的数!!是不是数字太大了,它hold不住!

恭喜你,就是这个原因了,记得我们说过的int是四个字节,简单的运算就能知道最大的数字范围是(自己百度或者计算怎么输出int最大范围,这个计算机编译器类型不一样,结果不一样我就不下结论了)

我们通过百度64的int最大范围是:



而和我们保持正常的最后一个数字(即出现负数最前面的一个数)对比如下

2147483647

2004189184

很明显,这个是最后的极限,所以输出来下一个数就马上挂了呀。。。。


我们开开心心地int  hold不住我们就用long long类型(长整)嘛!!再来一个!

改上去,很开心的 run ! 结果一看,还是一摸一样啊!!!这个时候估计你心里是奔溃的,但是不弃不馁!

我们思考,已经用了long long 还不够大,你还想怎么样!  可是你有没有想过long long还是有点浪费哦,为什么?它拿了一半去表示负数了

对哦!!我们用 unsigned long long ,问你怕未!

结果改成:

   unsigned long long i, temp, sum = 0;
    
    temp = 1;
    
    for(i = 1; i <= 5; i++)
        
    {
        
        temp = temp * i;
        
        sum = sum + temp;
        
        printf("temp is :%lld\n", temp);
    }
    
    printf("sum = %lld", sum);



终于,把这道看似非常简单,但内涵乾坤的题目给搞掂了!所以啊,严谨的逻辑思维除了我说的感觉以外,更多的是练习练习练习!



总结:

每一个大的课题和感觉收获都要有总结~


1.其实不是每个程序都要像我上面这样战战兢兢,如履薄冰,只是对大数特有的敏感一定要小心,因为计算机的的确确的数据类型是有限制范围的,如果hold不住就要出事了

所以大数一定要考虑数据类型的范围


2.学会优化程序


3.学会检验程序,你刚开始连检查程序都没有,我们输入20结果太大,可以输入小的数嘛,可以达到手算验证的效果


4.程序是基于数学理论基础的,这种敏感性怎么去培养?说个故事吧!









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值