我有一个算法可以将浮点数/双精度数比较为0。
类似的东西:
Matcher m = Pattern.compile("[^-_.\\w]",Pattern.UNICODE_CHARACTER_CLASS).matcher(input);
output = m.replaceAll("");
我想知道是否有更快的方法可以做到这一点? 这在我的微基准测试中表现得更快(5-7%)。
"%;アレルギー[]{}=abceⸯd漢字ру́сский"
答案 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%。这可能是由于不必调用无法内联的方法。
还应注意这两种方法不会返回相同的值。这是因为double
和float
的精度不同。如果您正在使用花车,请使用花车。与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"));
}
}