2015-11-06 26 views
1

我有這樣的功能:我可以加快我的特殊輪功能嗎?

int round(double val) { 
    if (val >= 0) { 
     return (int)Math.Floor(val + 0.5); 
    } 
    return (int)Math.Ceiling(val - 0.5); 
} 

我把它在我的計劃中有許多次,我的意思是很多次,所以它的每一個milisecond的運行時間的問題。有沒有比現在更快的方法? THX

編輯:

的功能是用於在圖像中計算的線的切線方向的算法的一部分。它來自學術文章。由於它以弧度值處理角度,因此它使用小而精確的數字。

I/O的例子:

0 -> 0 
1 -> 1 
1.1 -> 1 
1.51 -> 2 
-0.1 -> 0 
-1 -> -1 
-1.1 -> -1 
-1.51 -> -2 

EDIT2:

根據意見,我改變檢查功能,這一個:

int round(double val) { 
    return (int)Math.Round(val, MidpointRounding.AwayFromZero); 
} 

更新的問題是:數學.Round功能是最快的舍入方式?

+0

你剛纔不是執行'Math.Round'用'MidpointRounding.AwayFromZero'? –

+1

根據你的輸出,這是'Math.Round'與'MidpointRounding.AwayFromZero' –

+0

當我深入研究它時,似乎我做了...... :-)但是,你能否提出做這樣的最快方法四捨五入? – Jarda

回答

2

可以加快速度。這是更快的幾倍:

 if (val >= 0) 
     { 
      return (int)(val + 0.5d); 
     } 
     return = (int)(val - 0.5d); 

您避免所有這些數學庫的東西。問題是,它真的很重要嗎?對於1500000次轉換,您首次使用的時間爲18ms。你的EDIT2功能是36ms。這個功能是4ms。

根據此測量,處理器可以比較兩個雙打,添加兩個雙打,並在大約2.5ns內轉換一個。但是,如果它沒有在緩存中,從主內存讀取可能需要100ns。測量有時可能會產生誤導。

下面是完整的代碼

#region stopky 

     public class Stopky 
     { 
      [System.Runtime.InteropServices.DllImport("kernel32.dll")] 
      private static extern bool QueryPerformanceFrequency(out long frequency); 

      [System.Runtime.InteropServices.DllImport("kernel32.dll")] 
      private static extern bool QueryPerformanceCounter(out long ticks); 

      protected static double frequency = -1; 

      public void setStart() 
      { 
       QueryPerformanceCounter(out tickStart); 
      } 

      public double getTimeFromStart 
      { 
       get 
       { 
        QueryPerformanceCounter(out tickNow); 
        double time = (tickNow - tickStart)/frequency; 
        return time; 
       } 
      } 

      private long tickStart; 
      private long tickNow; 

      public Stopky() 
      { 
       if (frequency < 0) 
       { 
        long tmp; 
        QueryPerformanceFrequency(out tmp); 

        if (tmp == 0) 
        { 
         throw new NotSupportedException("Error while querying " 
       + "the high-resolution performance counter."); 
        } 

        frequency = tmp; 
       } 

       setStart(); 
      } 

      public void Show() 
      { 
       MessageBox.Show(this.getTimeFromStart.ToString()); 
      } 


     } 

     #endregion 




     private void button2_Click(object sender, EventArgs e) 
     { 
      double[] examples = new double[] { 0, 1, 1.1, 1.51, -0.1, -1, -1.1, -1.51 }; 

      int totalCount = 1500000; 

      double[] examplesExpanded = new double[totalCount]; 

      for (int i = 0, j = 0; i < examplesExpanded.Length; ++i) 
      { 
       examplesExpanded[i] = examples[j]; 

       if (++j >= examples.Length) { j = 0; } 
      } 

      int[] result1 = new int[totalCount]; 
      int[] result2 = new int[totalCount]; 
      int[] result3 = new int[totalCount]; 

      Stopky st = new Stopky(); 
      for (int i = 0; i < examplesExpanded.Length; ++i) 
      { 
       result1[i] = (int)Math.Round(examplesExpanded[i], MidpointRounding.AwayFromZero); 
      } 
      st.Show(); 
      st = new Stopky(); 
      for (int i = 0; i < examplesExpanded.Length; ++i) 
      { 
       double val = examplesExpanded[i]; 
       if (val >= 0) 
       { 
        result2[i] = (int)Math.Floor(val + 0.5); 
       } 
       result2[i] = (int)Math.Ceiling(val - 0.5); 
      } 
      st.Show(); 
      st = new Stopky(); 
      for (int i = 0; i < examplesExpanded.Length; ++i) 
      { 
       double val = examplesExpanded[i]; 
       if (val >= 0) 
       { 
        result3[i] = (int)(val + 0.5d); 
       } 
       else 
       { 
        result3[i] = (int)(val - 0.5d); 
       } 
      } 
      st.Show(); 

      for (int i = 0; i < totalCount; ++i) 
      { 
       if(result1[i] != result2[i] || result1[i] != result3[i]) 
       { 
        MessageBox.Show("ERROR"); 
       } 
      } 
      MessageBox.Show("OK"); 

     } 

的一些注意事項

  • 我< examplesExpanded.Length是略快於我< TOTALCOUNT,雖然它是直覺。原因是,範圍檢查可以避免。
  • 發行可顯著快於調試(這裏是差別不大)
+0

謝謝,這正是我正在尋找的答案...我已經做了一個基準測試,並且您的圓形函數版本比我的原始函數快10倍,比使用AwayFromZero舍入的函數快20倍 – Jarda

0

爲什麼不使用內置的Math.Round方法?

int round(double val) { 
    if (val >= 0) { 
     return Math.Round(val, MidpointRounding.AwayFromZero); 
    } 
    return Math.Round(val, MidpointRounding.ToEven); 
} 

https://msdn.microsoft.com/en-us/library/system.math.round(v=vs.110).aspx

+0

我不認爲你的建議是正確的 - 例如,當我有val = -5時,那麼你將返回-6,但我的將返回-5 ...並且存在正值的問題 – Jarda

+0

也許我誤解了你正在做的事情。你是否可以用一些示例輸入和輸出來編輯你的問題,以及爲什麼你的方法寫得像現在這樣? – Steve

+0

查看我編輯的詳細信息 – Jarda

相關問題