我遇到了一些具体的问题,自己无法很好地解释,希望您能回答以下问题:a)为什么会这样?b)如何最佳处理这些情况?
我的第一个问题是关于Math.pow。我已经在StackOverflow上找到了一些很好的解释(a),但不知道该怎么做(b)。我的基准程序如下:
Stopwatch watch = new Stopwatch(); // from the Diagnostics class
watch.Start();
for (int i = 0; i < 1000000; i++)
double result = Math.Pow(4,7) // the function call
watch.Stop()
结果并不理想(在我的电脑上大约需要300毫秒)(我已经运行了10次测试并计算了平均值)。
我的第一个想法是检查这是否是因为它是静态函数。所以我实现了自己的类。
class MyMath
{
public static double Pow (double x, double y) //Using some expensive functions to calculate the power
{
return Math.Exp(Math.Log(x) * y);
}
public static double PowLoop (double x, int y) // Using Loop
{
double res = x;
for(int i = 1; i < y; i++)
res *= x;
return res;
}
public static double Pow7 (double x) // Using inline calls
{
return x * x * x * x * x * x * x;
}
}
我检查的第三件事是,我是否可以直接通过4*4*4*4*4*4*4来替换Math.Pow(4,7)。
结果是(10次测试平均值)
300 ms Math.Pow(4,7)
356 ms MyMath.Pow(4,7) //gives wrong rounded results
264 ms MyMath.PowLoop(4,7)
92 ms MyMath.Pow7(4)
16 ms 4*4*4*4*4*4*4
现在我的情况基本上是这样的: 不使用Math.Pow。我的唯一问题就是...我真的必须现在实现自己的Math-class吗?仅仅为了实现幂运算函数,似乎有点低效。(顺便说一下,PowLoop和Pow7在Release版本中甚至比Math.Pow快约25%)。
所以我的最终问题是:
a) 如果我根本不使用Math.Pow(但对于分数可能会用到),那么我错了吗?(这让我感到有点难过)。
b) 如果您要优化代码,您是否真的直接编写所有这些数学运算操作的代码?
c) 也许已经有一个更快(开源^^)的数学运算库吗?
d) 我提出这个问题的原因基本上是:我假定.NET Framework本身已经为这些基本操作提供了非常优化的代码/编译结果——无论是Math-Class还是处理数组,我有点惊讶于写自己的代码能获得多少好处。在C#中,还有其他一些通用的“领域”或其他需要注意的地方吗?
Math.Pow
应该有一个重载版本,可以接受int
指数,因为这是最常见的情况,并且可以运行得更快。 - Richie Cotton