求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);
修改答案:
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.程序是基于数学理论基础的,这种敏感性怎么去培养?说个故事吧!