簡體   English   中英

使C#算法更有效

[英]Make C# algorithm more efficient

我有一個C#方法,它將一個數字的值從一個區間投射到一個目標區間。
例如:我們的間隔為-1000和9000,值為5000; 如果我們想將此值投影到0..100的間隔,我們得到60。

這是方法:

/// <summary>  
/// Projects a value to an interval
/// </summary>
/// <param name="val">The value that needs to be projected</param>  
/// <param name="min">The minimum of the interval the value comes from</param>  
/// <param name="max">The maximum of the interval the value comes from</param>  
/// <param name="intervalTop">The minimum of the interval the value will 
/// be projected to</param>  
/// <param name="intervalBottom">The maximum of the interval the value will 
/// be projected to</param>  
/// <returns>Projected value</returns> 
public decimal ProjectValueToInterval(decimal val,  
                                      decimal min,  
                                      decimal max,  
                                      decimal intervalBottom, 
                                      decimal intervalTop)  
{  
    decimal newMin = Math.Min(0, min);
    decimal valueIntervalSize = Math.Abs(max - newMin);
    decimal targetIntervalSize = Math.Abs(intervalTop - intervalBottom);

    decimal projectionUnit = targetIntervalSize / valueIntervalSize;

    return (val * projectionUnit) + Math.Abs((newMin * projectionUnit));
}

需要為數千個值調用此方法。
我想知道在C#中是否有更有效的方法來做到這一點? 如果是,您建議做出哪些改變?

只有數千個價值觀? 你真的需要進一步優化嗎? 我無法想象它現在實際上是一個瓶頸。 您是否已對該應用進行了分析,以確定這確實是一個問題?

鑒於該方法是O(1),您不會進行通常目標最激烈的優化 - 提高復雜性。

話雖如此 - 當你召喚這幾千次時,任何一個值是否保持不變? 例如,您是否重復使用相同的最小值和最大值? 如果是這樣,您可以創建一個類,它在構造函數中獲取這些值並預先計算它可以執行的操作,然后使用一個方法獲取其余參數。 這會略微改善一些事情,但我回到原來的觀點 - 只有在實際導致問題時才會擔心這一點。

答案是:不要使用小數進行快速操作。

有浮動或雙重不適合你的原因嗎?

只是數學。 你所謂的“投射”是范圍AB和A'-B'的標准化,這樣:

比率r =(xA)/(BA)=(y-A')/(B'-A')

使用您的條款是:

(val-min)/(max-min)=(returnValue-intervalBottom)/(intervalTop-intervalBottom)

它解決了returnValue:

returnValue =  ((intervalTop-intervalBottom) * (val-min) / (max-min)) + intervalBottom

除了已經建議的不使用Decimal之外,你可以在其他地方放棄你的最大/最小值,這樣你就不需要在所有地方進行所有那些Abs調用。

我懷疑你需要重復做的部分只是一個浮點乘以浮點加法后跟(或繼續)。 其他所有內容都可以預先檢查和預先計算。

您的代碼看起來比實際需要的更復雜。 公式是:

intervalTop + (intervalBottom - intervalTop) * (val - min) / (max - min);

這比你的版本簡單得多(適用於整數類型)。 那里沒有條件分支(Math.Min調用)或方法調用。 好的,它假設intervalTop <intervalBottom和min <max。 如果intervalTop,intervalBottom,min和max對於一組值是常量,那么您可以預先計算(intervalBottom - intervalTop)和(max - min)並將這些結果用於對函數的所有調用。 您可以消除的另一個開銷是將函數內聯到調用循環中。 我不知道C#(或者說JIT編譯器)對內聯方法做了什么,所以這可能已經在幕后發生了。

如果您可以使用整數或浮點數據類型,一種可能的解決方案是使用SIMD,但這意味着編寫可能會破壞您的要求的本機匯編程序代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM