任何人都知道乘法运算符是否比使用Math.Pow方法更快?像:
n * n * n
VS
Math.Pow ( n, 3 )
答案 0 :(得分:37)
我刚刚重新安装了Windows,因此未安装visual studio并且代码很难看
using System;
using System.Diagnostics;
public static class test{
public static void Main(string[] args){
MyTest();
PowTest();
}
static void PowTest(){
var sw = Stopwatch.StartNew();
double res = 0;
for (int i = 0; i < 333333333; i++){
res = Math.Pow(i,30); //pow(i,30)
}
Console.WriteLine("Math.Pow: " + sw.ElapsedMilliseconds + " ms: " + res);
}
static void MyTest(){
var sw = Stopwatch.StartNew();
double res = 0;
for (int i = 0; i < 333333333; i++){
res = MyPow(i,30);
}
Console.WriteLine("MyPow: " + sw.ElapsedMilliseconds + " ms: " + res);
}
static double MyPow(double num, int exp)
{
double result = 1.0;
while (exp > 0)
{
if (exp % 2 == 1)
result *= num;
exp >>= 1;
num *= num;
}
return result;
}
}
结果:
csc / o test.cs
test.exe
MyPow: 6224 ms: 4.8569351667866E+255
Math.Pow: 43350 ms: 4.8569351667866E+255
通过平方计算(参见 https://stackoverflow.com/questions/101439/the-most-efficient-way-to-implement-an-integer-based-power-function-powint-int)比我测试中的Math.Pow快得多(我的CPU是2 Ghz的Pentium T3200)
编辑:.NET版本是3.5 SP1,操作系统是Vista SP1,电源计划是高性能。答案 1 :(得分:28)
基本上,您应该基准来查看。
如果某些编译器没有对同一件事进行优化......
x * x * x
很可能比Math.Pow(x, 3)
更快,因为Math.Pow
必须在一般情况下处理问题,处理分数权力和其他问题,而{{1}只需要一些乘法指令,所以它很可能会更快。
答案 2 :(得分:6)
图像处理优化10年以上的一些经验法则科学计算:
算法级别的优化在低级别上优于任何数量的优化。尽管“写明显,然后优化”的传统智慧必须在一开始就完成。不是之后。
手动编码的数学运算(尤其是SIMD SSE +类型)通常会优于完整的错误检查,广义的内置运算。
编译器优化了编译器预先知道需要完成什么操作的任何操作。这些包括:
1.内存操作,如Array.Copy()
2.对于给定数组长度的数组的循环。与(..; i<array.Length;..
)
始终设定不切实际的目标(如果您愿意)。
答案 3 :(得分:6)
我昨天碰巧测试了这个,然后现在看到了你的问题。
在我的机器上,运行1个测试线程的Core 2 Duo,使用倍数最多可达9倍。在10,Math.Pow(b,e)更快。
然而,即使在2倍的情况下,结果通常也不相同。存在舍入错误。
某些算法对舍入误差非常敏感。在我发现这一点之前,我必须完成超过一百万次随机测试。
答案 4 :(得分:4)
这是微观的,您可能应该针对特定平台进行基准测试,我认为Pentium Pro的结果不一定与ARM或Pentium II相同。
总而言之,它最有可能完全无关紧要。
答案 5 :(得分:4)
我查了一下,Math.Pow()
被定义为两个双打。这意味着它不能重复乘法,但必须使用更通用的方法。如果有Math.Pow(double, int)
,则可能效率更高。
话虽如此,性能差异几乎肯定是微不足道的,所以你应该使用哪个更清楚。像这样的微优化几乎总是毫无意义,几乎可以在任何时候引入,并且应该留在开发过程的最后阶段。此时,您可以检查软件是否太慢,热点在哪里,并将微优化工作花在实际上会产生影响的地方。
答案 6 :(得分:2)
让我们使用约定x ^ n。我们假设n总是一个整数。
对于较小的n值,无聊乘法会更快,因为Math.Pow(可能依赖于实现)使用花哨的算法来允许n为非整数和/或负数。
对于较大的n值,Math.Pow可能会更快,但如果你的库不是很聪明,它将使用相同的算法,如果你知道n总是一个整数,这是不理想的。为此,您可以编写exponentiation by squaring或其他一些奇特算法的实现。
当然,现代计算机速度非常快,您可能应该坚持使用最简单,最容易阅读,最不可能是错误的方法,直到您对程序进行基准测试,并确保通过使用不同的算法获得显着的加速。
答案 7 :(得分:1)
以下是关于inlined multiplication vs. Math.pow
主题的讨论显然Math.pow比较慢,但不是很多......
答案 8 :(得分:1)
我不同意手工构建的功能总是更快。余弦函数比我能编写的任何函数都更快,更准确。至于pow()。我做了一个快速测试,看看Math.pow()在javascript中有多慢,因为Mehrdad告诫不要猜测
for (i3 = 0; i3 < 50000; ++i3) {
for(n=0; n < 9000;n++){
x=x*Math.cos(i3);
}
}
结果如下:
Each function run 50000 times
time for 50000 Math.cos(i) calls = 8 ms
time for 50000 Math.pow(Math.cos(i),9000) calls = 21 ms
time for 50000 Math.pow(Math.cos(i),9000000) calls = 16 ms
time for 50000 homemade for loop calls 1065 ms
如果您不同意,请尝试http://www.m0ose.com/javascripts/speedtests/powSpeedTest.html
上的程序答案 9 :(得分:0)
Math.Pow(x, y)
通常在内部计算为Math.Exp(Math.Log(x) * y)
。 Evey幂方程需要找到一个自然对数,一个乘法,并将e
提升到一个幂。
正如我在之前的回答中所提到的,只有10的幂才Math.Pow()
变得更快,但如果使用一系列乘法,精度会受到影响。
答案 10 :(得分:-2)