繁体   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