最快的Math.Max(值,0)

时间:2015-06-09 18:12:19

标签: c# performance

我有一个算法可以将浮点数/双精度数比较为0。

类似的东西:

Matcher m = Pattern.compile("[^-_.\\w]",Pattern.UNICODE_CHARACTER_CLASS).matcher(input);
output = m.replaceAll("");

我想知道是否有更快的方法可以做到这一点? 这在我的微基准测试中表现得更快(5-7%)。

"%;アレルギー[]{}=abceⸯd漢字ру́сский"

3 个答案:

答案 0 :(得分:2)

写一个小基准,这是我的结果:

  

您的版本:~2.3ms

     

优化版:~1.4ms

以下是代码:

float[] data = new float[150000];
Random rnd = new Random(12345);

for (int i = 0; i < data.Length; i++)
{
    data[i] = (float)(rnd.NextDouble() * 5000.0 - 2500.0);
}

Stopwatch sw = new Stopwatch();

sw.Start();

var varsum = 0.0;  //varsum is a DOUBLE!!!!

for (int i = 0; i < data.Length; i++)
    varsum += Math.Max(data[i], 0);        //implicit conversions, float->double, int->float

sw.Stop();

Console.WriteLine("Varsum : " + varsum);

Console.WriteLine("Time it took for the original: " + sw.Elapsed.TotalMilliseconds + " ms");

float floatsum = 0.0f;

sw.Reset();
sw.Start();

floatsum = 0.0f;

for (int i = 0; i < data.Length; i++)
    if (data[i] > 0.0f)
        floatsum += data[i];

sw.Stop();

Console.WriteLine("OptimizedSum: " + floatsum);

Console.WriteLine("Time it took for \"optimized\" version: " + sw.Elapsed.TotalMilliseconds + " ms");

//Equality on floating point numbers doesn't work like this, but...
Console.WriteLine("Are these two equal? " + (floatsum == varsum).ToString());
Console.WriteLine("How close are they? " + Math.Abs(floatsum - varsum).ToString("00.0000000000000000"));

Console.ReadKey(true);

控制台应用程序,32位进程,运行调试模式,为AnyCPU编译。第二个版本快了大约60%。这可能是由于不必调用无法内联的方法。

还应注意这两种方法不会返回相同的值。这是因为doublefloat的精度不同。如果您正在使用花车,请使用花车。与double相同,不要来回转换。上面的例子给了我超过65的差异!

小提琴:https://dotnetfiddle.net/S5qmCg(小提琴版并没有反映上述相同的时间值,我假设因为它的资源在服务器端有限,所以请尝试使用自己的计算机)

答案 1 :(得分:2)

您当前的代码是:

var sum = 0.0;
for(int i=0;i<data.Length;i++)
  sum += Math.Max(data[i],0);

Math.Max正在执行此操作:

public static double Max(double val1, double val2) 
{
    if (val1 > val2)
        return val1;

    if (Double.IsNaN(val1))
        return val1;

    return val2;
}

如果您知道自己不会NaN,请在没有Max支票的情况下实施自己的NaN

public static double Max(double val1, double val2) 
{
    if (val1 > val2)
        return val1;

    return val2;
}

答案 2 :(得分:0)

取决于您的阵列(和您的机器)的大小。根据阵列的大小,这在我的机器上要快得多:

using System;
using System.Diagnostics;
using System.Linq;

public class Program
{
    public static void Main()
    {
        float[] data = new float[1500000];
        Random rnd = new Random(12345);

        for (int i = 0; i < data.Length; i++)
        {
            data[i] = (float)(rnd.NextDouble() * 5000.0 - 2500.0);
        }

        Stopwatch sw = new Stopwatch();

        sw.Start();

        var varsum = 0.0f;  //varsum is a DOUBLE!!!! change this to 0.0f to make them equal!

        for (int i = 0; i < data.Length; i++)
            varsum += Math.Max(data[i], 0);        //implicit conversions, float->double, int->float

        sw.Stop();

        Console.WriteLine("Varsum : " + varsum);

        Console.WriteLine("Time it took for the original: " + sw.Elapsed.TotalMilliseconds + " ms");

        float floatsum = 0.0f;

        sw.Reset();
        sw.Start();

        floatsum = 0.0f;
        floatsum=data.AsParallel().Where(d=>d>0).Sum();

        sw.Stop();

        Console.WriteLine("OptimizedSum: " + floatsum);

        Console.WriteLine("Time it took for \"optimized\" version: " + sw.Elapsed.TotalMilliseconds + " ms");

        //Equality on floating point numbers doesn't work like this, but...
        Console.WriteLine("Are these two equal? " + (floatsum == varsum).ToString());
        Console.WriteLine("How close are they? " + Math.Abs(floatsum - varsum).ToString("00.0000000000000000"));

    }
}