现在的位置: 首页 > 综合 > 正文

【程序语言】程序循环的那些事儿

2018年04月30日 ⁄ 综合 ⁄ 共 2637字 ⁄ 字号 评论关闭

   我一直认为循环是程序的发动机,所以决定深入探究一下循环的那些事儿!

   下面我们研究一下循环的写法和效率:

   背景是这假设有一个存放20个元素的数组int arr[20],我们想对它进行求和,也就arr[0]+arr[1]+…… 好的,在这个简单的背景下,我们开始我们的探索吧!

 

  1.第一个富有建设性的版本诞生了,她是那么的直观,那么的整洁,嘻嘻:   

     int sum = 0;
         sum =  arr[0]  +arr[1]  +arr[2]  +arr[3]
               +arr[4]  +arr[5]  +arr[6]  +arr[7]
               +arr[8]  +arr[9]  +arr[10] +arr[11]
               +arr[12] +arr[13] +arr[14] +arr[15]
               +arr[16] +arr[17] +arr[18] +arr[19]; 

     也许你觉得最初级的程序员都不会写出这样的代码的,但请不要鄙视这种写法!真的,也许某一天你会喜欢上这个版本的!

  2.第二个版本是百分之80的程序员都会这么写的一种最普通的写法:

     int sum=0;
     for(int i=0; i<20; i++)
     {    sum += arr[j];    }

 这个版本是不是忒熟悉,忒顺眼,忒良好,忒精简。嘿嘿,也忒普通!

  3.第三个版本来自第二个版本的改良。什么?第二个还可以改良,骗人吧!没骗你:   

    int sum=0;
    for(int i=0; i<20; ++i)
     {    sum += arr[i];    }

     神啊,请问这也叫改良吗?几乎没动过嘛!错,i++改成了++i。这也叫改良吗? 当然算改良,要不,你自己测测效率就知道了。

 

  4.第四个版本来自C++版本的指针,其他语言不用担心,其实语言编译器也用指针的,嘿嘿。

     int sum=0;
     for(int i=0; i<20; ++i)
     {   sum += *(arr+i);  }

     用指针有什么好的?因为 arr[i] 会被翻译成 *( arr + i*sizeof(int) ) ,有差别吗?当然有啦。但是这是在古老的编译器中,现代流行的编译器中,其实有优化过了,arr[i]和*    (arr+i)基本没区别了!

 

   5.最后的一个版本来自元编程(metaprogramming),编译型语言在理论上支持元编程。现在貌似Ruby也支持元编程,但这里还是以C++为例子好了,大家熟悉点儿嘛。

     template <int Dim,typename T>
      struct Sum{
         static T sum(T *arr){
            return (*arr) + Sum<Dim-1,T>::sum(arr+1);
         };
      };
    template<typename T>
      struct Sum<1,T>{
        static T sum(T *arr){
           return *arr;
        };
      };

   int sum = Sum<20,int>::sum(arr);

 你骗人这算什么熟悉!!!呵呵,有不熟悉,才有熟悉嘛!这是一种挖掘编译器潜力的编程方法,是一种用来生成代码的编程方式。例如这个版本的求和,你不要以为她调用了任何函数,其实她和第一个版本是一摸一样的,编译器会自动将代码展开到第一个版本的形式。

    现在,是时候看看这五个版本的循环有什么区别了。为保证公平,我对每段代码都循环执行1,000,000,000次,下面就是我们期待良久的结果了:

                   第一次     第二次     第三次    第四次

      版本1:0              0              0            0

      版本2:8290        8180        8200      8250

      版本3:8090        8160        8070      8234

      版本4:8252        8140        8050      8460

      版本5:10            0              0            0

   嘻嘻,看结果什么感觉,说过不要轻视第一个版本吧,你真有可能什么时候需要她呢!i++和++i还是有区别的哦!至少我测试了很多次,一直都是++i快那么一点儿,虽然不多。第5个元编程版本什么感受呢?

 

 结论:

   1.不要轻视那些最直观的傻瓜式编程,或许计算机本身最擅长的就是这个!

   2.i++和++i还是有区别的,有兴趣可以看看左值和右值的区别,另外i++和i++还涉及到一个中间变量问题。

   3.在现代C++中还是少使用指针运算了。多态和智能指针sharedptr除外!

   4.元编程是生成代码的编程,可能在需要极致效率的时候,而程序中存在常量的时候,元编程是个选择。

 

说明一下“开发效率”和“执行效率”的均衡:

   1.一个程序员 一年的 工资 按中国的平均年薪算 6W.

   2.一台服务器按一般的配置算1W

现在需要写一个程序:假设有两个实现版本,四家公司用。

   1.X版本注重开发效率,需要    2  个月 5   人团队完成.

   2.Y版本注重执行效率,需要 10  个月 25 人团队完成.

   3.A公司是一家小公司,需要程序运行在    2              台服务器上,服务于2,000               人左右.

   4.B公司是一家小公司,需要程序运行在   10             台服务器上,服务于10,000             人左右.

   5.C公司是一家大公司,需要程序运行在   10,000      台服务器上,服务于10,000,000      人左右.

   6.D公司是一家大公司,需要程序运行在   1,000,000 台服务器上,服务于1,000,000,000 人左右.

其实,对程序成本进行简略计算,程序员加管理成本,简单计算为12W每年每人。X版本程序成本10W,

Y版本程序成本250W。假设 Y 比 X 效率高 5%, 那么就会节省 5%的服务器,

   1.对 A 公司而言,节省了 0.1       台服务器,如果使用 Y 版本,亏损    239.9W.

   2.对 B 公司而言,节省了 0.5       台服务器,如果使用 Y 版本,亏损    239.5W.

   3.对 C 公司而言,节省了 500      台服务器,如果使用 Y 版本,净赚    260.0W.

   4.对 D 公司而言,节省了 10,000 台服务器,如果使用 Y 版本,净赚 9,760.0W.

这就是一种衡量,小公司要的是开发效率,恨不得所有东西都可以用Ruby写,大公司要的是效率,恨不得

“所有程序都可以用汇编写!”. 

 

抱歉!评论已关闭.