for循环中一个不容小觑的问题

for(int i=1;i<=100;i++)

作为程序猿,我们很喜欢使用这种for循环。

可是,当中隐含着一个重要的问题。

过多的编程经历可能使我们的思维产生了一些误解,在上面的for循环中,因为我们在以往过多的编程经历中更加关注for循环体中的内容,导致我们差点儿忽略了那个小i的存在,它扮演着作为计数器的一个“小角色”,我们忽略了它,殊不知它的“饭量”也是不小的哦~

#include<stdio.h>
#include<time.h>
int main()
{
    int temp;
    /********************************/
    temp=clock();
    for(int i=1;i<=100;i++);
    printf("%d\n",clock()-temp);
    /********************************/
    temp=clock();
    for(int i=1;i<=1000000000;i++);
    printf("%d\n",clock()-temp);
    /********************************/
    return 0;
}

程序执行结果是:

0

3000

这样看来,那个小i所耗掉的执行时间也是很可观的。一些编程新手觉得程序的执行时间是由循环次数决定的,这样说对于上面的那个程序貌似是对的,可是没有说到本质。略微懂编程的人都能知道,程序的执行时间是由程序的运算次数决定的,明显加减法要比乘除法快。

对于觉得执行时间由循环次数决定的想法是错误的,能够看以下的程序:

#include<stdio.h>
#include<time.h>
int main()
{
    int n,temp;
    /********************************/
    temp=clock();
    n=1;
    for(int i=1;i<=100000000;i++)
    {
        n++,n--;
        n++,n--;
        n++,n--;
        n++,n--;
        n++,n--;
        n++,n--;
        n++,n--;
        n++,n--;
        n++,n--;
        n++,n--;
    }
    printf("%d\n",clock()-temp);
    /********************************/
    temp=clock();
    n=1;
    for(int i=1;i<=150000000;i++)n++,n--;
    printf("%d\n",clock()-temp);
    /********************************/
    return 0;
}

程序执行结果:

6291

901

前者的循环次数有一亿次,而后者的循环次数有一亿五千万次,可是后者更快,是由于前者的运算次数多。深入分析,前者的加减法运算次数大约是100000000+100000000*20=2100000000即21亿,比較次数(i<=100000000)是一亿次;而后者加减法运算次数是150000000+150000000*2=450000000即4亿5千万次,比較次数(i<=150000000)是一亿五千万次。前者比后者多了16亿5千万次的加减法,后者比前者多了5千万次的比較,依据数据大小的不同可能会有所差异。

不管怎样,我们一方面要认识到决定执行时间的因素究竟有哪些,还有一方面,我们更不能忽视掉for循环中小i的作用和消耗,尤其在小i嵌入一个二层循环中。

我之前做过一道算法题,我的程序要跑4s,而我同学给我优化的程序仅仅要跑不到1s,可是我始终找不到原因,由于推导的公式中累加的次数是一样的,仅仅只是我的循环是n*sqrt(n),而他的是n*lg(n)。我当时仅仅注重了公式中数据的累加,即我仅仅注重了循环体中的内容,忽视掉了小i也有做加法,尤其是套在一个数据量高达五十万的二层循环中,这时候,小i的影响就凸显出来了,由于在这个问题上,我和我的同学相差的地方仅仅有那个循环次数不一样了(公式中的累加肯定是一样的,不然得出的结果是不一样且不对的)。所以看来,有些时候须要特别的控制一下程序的循环次数,在算法一样的情况下,尤其对于多层循环的程序,降低循环次数可以出现意想不到的收益。

时间: 2024-10-12 19:42:59

for循环中一个不容小觑的问题的相关文章

Java循环中删除一个列表元素

本文主要想讲述一下我对之前看到一篇文章的说法.假设跟你的想法有出入,欢迎留言.一起讨论. #3. 在循环中删除一个列表元素 考虑以下的代码.迭代过程中删除元素: ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c", "d")); for (int i = 0; i < list.size(); i++

python3中 for line1 in f1.readlines():,for line1 in f1:,循环读取一个文件夹

1 #-*- encoding:utf-8 -*- 2 3 class loadDatas(object): 4 def __init__(self): 5 self.path='./data' 6 def load_compare(self): 7 l1={} 8 f1=open(self.path+'/95b.txt',encoding='utf-8') 9 l2={} 10 f2=open(self.path+'/05b.txt',encoding='utf-8') 11 f=open(s

不容小觑的SQLException:违反协议

最近太忙,太忙,简直就是昏天暗地.... 正在小猿我努力工作的时候,一个急速闪烁的头像把我拉回到现实中,现场程序在读取数据时报错:SQLException:违反协议,当时小猿我思维一滞,这是什么鬼.凭借我些许的码农经验,打开搜索引擎一顿搜索,正是众说纷纭,大家各有所言.但总结起来无非是两种论调: 1.驱动程序不匹配 2.数据存在问题(中文问题.字段类型.长度不一而足) 来吧,既然有方向,那就奋斗吧,首先看了一下驱动程序,数据库为Oracle10g(10.2.0.5),看了一下官网推荐的驱动为cl

P2P成长性不容小觑,金融工场交易额破7亿背后的启示

P2P网贷经历一段时间的洗礼,最近又呈现了健康.稳定的发展势头,9月22日,成立两周年的金融工场累计投资额超过7亿元,深刻诠释了P2P网贷"优胜劣汰"的发展格局,及其不容小觑的成长性. 野蛮增长到理性发展 众所周知,P2P网贷经历了野蛮生长和跑路潮之后,已经变得理性了许多,一方面,通过这种方式,P2P网贷也逐渐树立了自己的游戏规则,"三无"状态被逐渐打破,行业正呈现出一种欣欣向荣的态势.另一方面,投资者对P2P网贷也有了更深刻.更专业的认识,过去的教训迫使他们对P2

python 如何在一个for循环中遍历两个列表

是我在看<笨方法学python>过程中发现有一行代码看不懂——“ for sentence in snippet, phrase:”,所以研究了半天,感觉挺有收获的.所以就放在博客上分享给大家了. 直入主题: 为了不耽误大家时间,如果知道以下为两段代码为什么输出不一样的话我觉得您肯定知道我下面要说的是什么了,您就不必花时间再读下去了. 1和2两段代码的区别是print在for循环中,另外一个是不在循环中.输出的结果却截然不同,如果想要弄懂如何遍历两列表,花些时间把下面的几行代码弄懂.我要说的您

Handlebars.js循环中索引(@index)使用技巧(访问父级索引)

使用Handlebars.js过程中,难免会使用循环,比如构造数据表格.而使用循环,又经常会用到索引,也就是获取当前循环到第几次了,一般会以这个为序号显示在页面上. Handlebars.js中获取循环索引很简单,只需在循环中使用{{@index}}即可. 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <META http-equiv=Content-Type content="text/html; charset=utf-

while循环中使用scanf函数

妈的,这scanf函数学了快10年了,怎么还会出现莫名其妙的问题?看下面的代码(VS2012环境下运行): #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int main() { char root_value = '\0'; int i =1; while (i!=5) { printf("输入:"); scanf("%c",&root_value);//用户输入节点 i++; } prin

关于在for循环中绑定事件打印变量i是最后一次。

其实函数引用的外部变量都是最后一次的值. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> #box{ width:100px; height:100px; background-color:pink; } </style> <

【算法思想】循环移动一个数组

问题:如何将一个数组循环左移或者右移k位? 在下面的解决方案中,我们以循环左移为例. 我们最容易想到的是,将前k个元素复制到一个临时的数组中,然后将剩下的n-k个元素向左移动k个位置,然后将之前的k个元素复制到剩下的位置.这种方法使用了k个额外的存储空间.我们想到到另一种方法是,只借助一个临时空间,每次只向左移动1位,循环k次.这种方法产生了多于的运行时间.前面一篇文章中用程序实现了循环右移一个数组的算法.前面提到的都是比较常规的算法,下面从其它角度来考虑这一问题: 循环数组x其实就是交换数组x