置頂文章

您希望自己爆肝寫的程式碼不被別人盜取嗎?用goto就對了。
goto就像是任意門,可以自由自在的穿梭到任何地方,用了它,程式碼就會變的亂七八糟的,再也不怕別人盜取自己的程式碼了,goto是最強的跳躍語法,一生無悔控goto,一起用goto來保護自己的程式碼吧~

[轉貼]goto的效能比for和while快?


[不專業研究]for、while、goto效能評比

本文轉貼自友站  可雷塔的計算機科學研究所

我們常常聽說goto是一把雙面刃,它可以在程式碼中像任意門一樣穿梭自如,但是卻破壞了程式碼的結構與可讀性。

但是,goto的優點只有跳躍而已嗎?

本文將設計針對for、while、goto的效能做比較的實驗,探討goto是否能對程式碼的效能進行優化。

測試環境:
程式語言:C++
作業系統:Windows7
CPU:Intel i5-3470
使用IDE及編譯器:Visual Studio 2019
平台模式:64位元,debug模式(無最佳化)

以下是實驗程式碼:
 unsigned int length = 1024 * 1024 * 1024 * 10;
     int length2 = 1024 * 1024 * 1024;
     int key = 0;
std::cout << "一層迴圈\n" ;
     i = 0;
     clock.restart();
     for (i = 0;i < length;i++)
     {
          key = i;
     }
     std::cout << "for的時間為" << clock.GetTime() << "毫秒\n" ;


     i = 0;
     clock.restart();
     while (i < length)
     {
          key = i;
          i++;
     }
     std::cout << "while的時間為" << clock.GetTime() << "毫秒\n" ;

     i = 0;
     clock.restart();
flag0:
     key = i;
     i++;
     if (i < length) goto flag0;

     std::cout << "goto的時間為" << clock.GetTime() << "毫秒\n" ;


     std::cout << "二層迴圈\n" ;

     i = 0;
     j = 0;
     clock.restart();
     for (j = 0;j < 10;j++) {
          for (i = 0;i < length2;i++)
          {
                key = i;
          }
     }
     std::cout << "for的時間為" << clock.GetTime() << "毫秒\n" ;

     j = 0;
     i = 0;
     clock.restart();
     while (j < 10) {
          i = 0;
          while (i < length2)
          {
                key = i;
                i++;
          }
          j++;
     }
     std::cout << "while的時間為" << clock.GetTime() << "毫秒\n" ;

     i = 0;
     j = 0;
     clock.restart();
flag:
     i = 0;
flag2:
     key = i;
     i++;
     if (i < length2) goto flag2;
     j++;
     if (j < 10) goto flag;
     std::cout << "goto的時間為" << clock.GetTime() << "毫秒\n" ;

我們分別利用單層迴圈和雙層迴圈測試for、while、goto的效能。
首先,定義了一個 unsigned int的變數length,大小為1024 * 1024 * 1024 * 10。
然後分別設計for、while、goto的單層迴圈去運行它,次數為length。

然後,定義了一個  int的變數length2,大小為1024 * 1024 * 1024。
然後分別設計for、while、goto的雙層迴圈去運行它,次數為10*length2。

所以,單層迴圈和雙層迴圈運轉的次數是一樣的。

最後,我們在迴圈中加入了key=i,模擬實際迴圈中常見的狀況。

測試結果:

在一層迴圈中,for的效能最差,花費時間為4627毫秒,次之則為while,為4426毫秒,令人驚訝的是,goto的效能竟然最高,僅花費了4402毫秒。



然而,進入第二階段的雙層迴圈試驗,原本趨於劣勢的for迴圈竟逆轉局勢並驚險的勝出,花費了22026毫秒,而goto在這場比賽則敬陪末座,總花費時間為22119毫秒。

但是,真的只差了一點點,我們再重跑一次程式:


在第二次,在一層迴圈中,一樣是由goto勝出,但是呢,在雙層迴圈中,goto再次贏過for和while拿下勝利,總花費時間為22018毫秒,while則敬陪末座。

可見在第二層迴圈中,三者的速度是差不多的。

但是,如何讓goto在雙層迴圈中發揮它在單層迴圈的優勢呢?

我們再做個實驗
     unsigned int length = 1024 * 1024 * 1024 * 10;
     int length2 = 1024 * 1024 * 1024;
     int key = 0;

     i = 0;
     j = 0;
     clock.restart();
     for (j = 0;j < 10;j++) {
          for (i = 0;i < length2;i++)
          {
                key = i;
          }
     }
     std::cout << "for+for的時間為" << clock.GetTime() << "毫秒\n" ;

     i = 0;
     j = 0;
     clock.restart();
     for (j = 0;j < 10;j++)
     {
          i = 0;
     flag1:
          i++;
          key = i;
          if (i < length2)goto flag1;
     }


     std::cout << "for+goto的時間為" << clock.GetTime() << "毫秒\n" ;


     i = 0;
     j = 0;
     clock.restart();
flag3:
     i = 0;
     for (i = 0;i < length2;i++)
     {
          key = i;
     }
     j++;
     if (j < 10) goto flag3;
     std::cout << "goto+for的時間為" << clock.GetTime() << "毫秒\n" ;

在這一次,我們分別使用雙層for迴圈、外圈為for內圈為goto、外圈為goto內圈為for,來做測試,跑的次數跟上一次的實驗一樣。

測試結果:

果不其然,讓goto在內層迴圈,效能上會有顯著優勢,而放在外層則不具有優勢。

為了防止運氣問題,我們再讓程式跑一次:


一樣的,for+goto再度以19074毫秒壓倒性的勝出,for+for最差,為22196毫秒,goto+for則為22123毫秒


結論:
在單層迴圈中,goto在效能上會比for和while來的有優勢,而在雙層迴圈中,goto在內層迴圈中依然可以為效能帶來貢獻。

這次的for、while、goto不專業效能評比就到這邊結束了,如果有其他點子想測試的,歡迎留言一起來做討論,我們下次見囉!

利用goto,算出最小公倍數


            int number1=255, number2=800,number3=0,product=0;
            int temporarily = Math.Max(number1, number2);
            number2  = Math.Min(number1, number2);
            number1 = temporarily;
            product = number1 * number2;
            while1:
            number1 = number1 > number2 ? number1 : number2;
            number3 = number1 % number2;
            number1 = number2;
            number2 = number3;
            if (number2 != 0)
                goto while1;
            Console.Write(product/number1);

利用goto,算出最大公因數


            int number1=54, number2=24,number3=0;
            int temporarily = Math.Max(number1, number2);
            number2  = Math.Min(number1, number2);
            number1 = temporarily;
            while1:
            number1 = number1 > number2 ? number1 : number2;
            number3 = number1 % number2;
            number1 = number2;
            number2 = number3;
            if (number2 != 0)
                goto while1;
            Console.Write(number1);

利用goto,進行氣泡排序


                int[] list = new int[9] { 2, 4, 6, 7, 1, 9, 3, 8, 5 };
                int temporarily;
                Boolean  flag = true ; 
                int i=1;
                int j=1;
                for1:
                flag =false  ;
                j = 1;
                for2:                
                if (list[j] < list[j - 1])
                {    
                    temporarily  = list[j];
                    list[j] = list[j - 1];
                    list[j - 1] = temporarily;
                    flag = true ;
                }
                if (j<9-i)
                {
                    j += 1;
                    goto for2;
                }
                if (i < 8 && flag == true )
                {
                    i += 1;
                    goto for1;
                }
                j = 0;
                for3:
                Console.Write(list[j] + " ");
                j++;
                if (j < 9)
                    goto for3;

利用goto,印出九九乘法表


                  int X = 1;
                  int Y = 1;
                  for1:
                  Y = 1;
                  for2:
                  Y+= 1;
                  if (Y* X <= 9)                   
                    Console.Write(Y + "X" + X + "=0" + Y * X + " ");
                  else
                    Console.Write(Y + "X" + X + "=" + Y * X + " ");
                  if (Y <= 8)
                    goto for2;
                  X += 1;
                  Console.WriteLine();
                  if (X <= 9)
                    goto for1;

利用goto,印出倒三角形


                int triangle1 = 0;
                int triangle2 = 9;
                for1:
                triangle2 = 9;
                for2:
                triangle2 -= 1;
                Console.Write(0);
                if (triangle2 > triangle1)
                    goto for2;
                triangle1 += 1;
                Console.WriteLine();
                if (triangle1 < 9)
                    goto for1;