一题一会-算法入门第一期
任意次方后的最后三位
题目
编程求一个整数任意次方后的最后三位数,即求x^y的最后三位数,x和y的值由键盘输入。
代码
#include
void main()
{
int i,x,y,z=1;
printf("请输入两个数,x和y(x^y):\n");
scanf("%d%d",&x,&y); /*输入底数和幂数*/
for(i=1;i<=y;i++)
{
z=z*x%1000; /*计算任意一个整数任意次方后的最后三位数*/
}
if(z>100)
{
printf("%d^%d的最后三位是:%d\n",x,y,z); /*输出结果*/
}
else
{
printf("%d^%d的最后三位是:0%d\n",x,y,z); /*输出结果*/
}
}
tips
本例子中的算法思想如下:题目中要求一个数任意次方,首先要考虑计算结果是否越界,如何避免产生越界问题同时又不会使结果产生误差,这里的解决办法是在每乘一次方后都取其后三位,这样就不会出现越界问题,又可完成题目要求。
测试
如果未考虑到越界问题将for循环体中的代码修改为如下代码:
for(i=1;i<=y;i++)
{
z=z*x; /*计算任意一个整数任意次方*/
}
z=z%1000; /*计算后三位*/
本例中变量z定义的为int型,其最大值为2^31-1,如果z的值超过最大值将会发生越界问题,但是此处并未有语法错误,编译器在检查时是无法发现实际操作中可能引发的问题的。我们以2^32为输入,来测试上述两段代码。
修改前的代码运行结果即正确结果:
修改代码后的结果即错误结果:
利用计算器计算出的结果:
通过计算机运算结果可以验证未修改前的代码的确为正确代码。
思考
编程语言中的被定义了类型的数据并不像现实世界中的数据可以无穷大,每一个数据类型都对应的有一定的数值范围。在编程时要时刻思考越界问题是否存在,如果存在要怎么规避或者解决。数据一旦发生越界代码运行会产生不可预测、不可控的结果。在使用数组时尤其要注意越界问题,C/C++没有对数组做边界检查,不检查下标是否越界可以提升程序运行的效率。因此检查是否越界的任务就交给了开发人员,而在智能车开发中初期选手常用数组来操作数据,希望大家能加强此方面的意识。关于更加详细的越界问题及规避办法会在后期推出更加详细的推文。
此实例应该带给我们的另外一个思考是:如何准确的定义变量,如何合理的使用全局变量,静态变量等,以提高程序的运行效率和准确性。近年来智能车芯片能力越来越强,在一定程度上降低了上述问题的影响,但是性能较差的单片机仍需考虑上述问题,如第十五届使用的STC单片机算力明显不足,此时如何优化代码就显得格外重要。合理的利用资源,不造成资源的浪费是一个合格的程序猿应该考虑的事情。如在电磁循迹中通常8位ADC分辨率足够使用,因此将电磁采集变量定义为8位无符号类型即够用。但为了后续的计算方便,不再进行强制转换,也可将电磁采集变量定义为有符号类型,此时就需要定义为有符号16位类型。否则可能无法存储返回的电磁值,因为8位分辨率下返回的数值范围是0-255。
下期题目
婚礼上的谎言
3对情侣参加婚礼,3个新郎为A、B、C,3个新娘为X、Y、Z,有人想知道究竟谁与谁结婚,于是就问新人中的三位,得到如下结果:A说他将和X结婚;X说她的未婚夫是C;C说他将和Z结婚。这人事后知道他们在开玩笑,说的全是假话。那么,究竟谁与谁结婚呢?
打鱼晒网问题
如果一个渔夫从2011年1月1日开始每三天打一次渔,两天晒一次网,编程实现当输入2011年1月1日以后的任意一天,输出该渔夫是在打渔还是在晒网。
ps:前期文章为了使得大家更加容易接受和吸收,部分说法不够严谨,随着教学和学习的深入会逐步减少对基础概念的解释,所以请大家及时加强学习。若发现文章中有根本性的错误,请及时通过公众号与我联系。下期题目有完成者可提前发我批阅,将计入平时成绩----wildfire留