C# Math.Pow 与乘法运算符(性能)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/936541/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Math.Pow vs multiply operator (performance)
提问by Joan Venge
Anyone knows if multiply operator is faster than using the Math.Pow method? Like:
任何人都知道乘法运算符是否比使用 Math.Pow 方法更快?喜欢:
n * n * n
vs
对比
Math.Pow ( n, 3 )
采纳答案by Mehrdad Afshari
Basically, you should benchmarkto see.
基本上,您应该进行基准测试。
Educated Guesswork (unreliable):
有根据的猜测(不可靠):
In case it's not optimized to the same thing by some compiler...
如果它没有被某些编译器优化为相同的东西......
It's very likely that x * x * x
is faster than Math.Pow(x, 3)
as Math.Pow
has to deal with the problem in its general case, dealing with fractional powers and other issues, while x * x * x
would just take a couple multiply instructions, so it's very likely to be faster.
这很可能x * x * x
快于Math.Pow(x, 3)
作为Math.Pow
具有应对其通常情况下的问题,处理分数的权力等问题,而x * x * x
将只需要几个乘法指令,那么它很可能会更快。
回答by Henk Holterman
This is so micro that you should probably benchmark it for specific platforms, I don't think the results for a Pentium Pro will be necessarily the same as for an ARM or Pentium II.
这太微小了,您可能应该针对特定平台对其进行基准测试,我认为 Pentium Pro 的结果不一定与 ARM 或 Pentium II 的结果相同。
All in all, it's most likely to be totally irrelevant.
总而言之,它很可能完全无关紧要。
回答by David Thornley
I checked, and Math.Pow()
is defined to take two doubles. This means that it can't do repeated multiplications, but has to use a more general approach. If there were a Math.Pow(double, int)
, it could probably be more efficient.
我查了一下,并被Math.Pow()
定义为采取两次双打。这意味着它不能进行重复乘法,而必须使用更通用的方法。如果有Math.Pow(double, int)
,它可能会更有效率。
That being said, the performance difference is almost certainly absolutely trivial, and so you should use whichever is clearer. Micro-optimizations like this are almost always pointless, can be introduced at virtually any time, and should be left for the end of the development process. At that point, you can check if the software is too slow, where the hot spots are, and spend your micro-optimization effort where it will actually make a difference.
话虽如此,性能差异几乎可以肯定是绝对微不足道的,因此您应该使用更清晰的那个。像这样的微优化几乎总是毫无意义的,几乎可以在任何时候引入,并且应该留到开发过程的最后。在这一点上,您可以检查软件是否太慢,热点在哪里,并将您的微观优化工作花在真正会产生影响的地方。
回答by David
Let's use the convention x^n. Let's assume n is always an integer.
让我们使用约定 x^n。让我们假设 n 总是一个整数。
For small values of n, boring multiplication will be faster, because Math.Pow (likely, implementation dependent) uses fancy algorithms to allow for n to be non-integral and/or negative.
对于较小的 n 值,无聊的乘法会更快,因为 Math.Pow(可能取决于实现)使用花哨的算法来允许 n 为非整数和/或负数。
For large values of n, Math.Pow will likely be faster, but if your library isn't very smart it will use the same algorithm, which is not ideal if you know that n is always an integer. For that you could code up an implementation of exponentiation by squaringor some other fancy algorithm.
对于较大的 n 值,Math.Pow 可能会更快,但如果您的库不是很聪明,它将使用相同的算法,如果您知道 n 始终是整数,则这并不理想。为此,您可以通过平方或其他一些奇特的算法来编写取幂的实现。
Of course modern computers are very fast and you should probably stick to the simplest, easiest to read, least likely to be buggy method until you benchmark your program and are sure that you will get a significant speedup by using a different algorithm.
当然,现代计算机速度非常快,您应该坚持使用最简单、最容易阅读、最不可能出错的方法,直到您对程序进行基准测试并确定使用不同的算法会获得显着的加速。
回答by ggf31416
I just reinstalled windows so visual studio is not installed and the code is ugly
我刚刚重新安装了 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;
}
}
The results:
csc /o test.cs
结果:
csc /o test.cs
test.exe
测试程序
MyPow: 6224 ms: 4.8569351667866E+255
Math.Pow: 43350 ms: 4.8569351667866E+255
Exponentiation by squaring (see https://stackoverflow.com/questions/101439/the-most-efficient-way-to-implement-an-integer-based-power-function-powint-int) is much faster than Math.Pow in my test (my CPU is a Pentium T3200 at 2 Ghz)
通过平方取幂(参见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)
EDIT: .NET version is 3.5 SP1, OS is Vista SP1 and power plan is high performance.
编辑:.NET 版本为 3.5 SP1,操作系统为 Vista SP1,电源计划为高性能。
回答by Doug
A few rules of thumb from 10+ years of optimization in image processing & scientific computing:
来自 10 多年图像处理和科学计算优化的一些经验法则:
Optimizations at an algorithmic level beat any amount of optimization at a low level. Despite the "Write the obvious, then optimize" conventional wisdom this must be done at the start. Not after.
算法级别的优化击败了低级别的任何优化。尽管“写出明显的,然后优化”的传统智慧,这必须在开始时完成。不是之后。
Hand coded math operations (especially SIMD SSE+ types) will generally outperform the fully error checked, generalized inbuilt ones.
手工编码的数学运算(尤其是 SIMD SSE+ 类型)通常会优于完全错误检查的通用内置运算。
Any operation where the compiler knows beforehand what needs to be done are optimized by the compiler. These include:
1. Memory operations such as Array.Copy()
2. For loops over arrays where the array length is given. As in for (..; i<array.Length;..
)
编译器事先知道需要做什么的任何操作都由编译器优化。这些包括: 1. 内存操作,例如 Array.Copy() 2. For 在给定数组长度的数组上循环。至于 ( ..; i<array.Length;..
)
Always set unrealistic goals (if you want to).
总是设定不切实际的目标(如果你愿意的话)。
回答by dooder duderama
I disagree that handbuilt functions are always faster. The cosine functions are way faster and more accurate than anything i could write. As for pow(). I did a quick test to see how slow Math.pow() was in javascript, because Mehrdad cautioned against guesswork
我不同意手工构建的函数总是更快。余弦函数比我能写的任何东西都更快、更准确。至于 pow()。我做了一个快速测试,看看 Math.pow() 在 javascript 中有多慢,因为 Mehrdad 告诫不要猜测
for (i3 = 0; i3 < 50000; ++i3) {
for(n=0; n < 9000;n++){
x=x*Math.cos(i3);
}
}
here are the results:
结果如下:
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
if you don't agree try the program at http://www.m0ose.com/javascripts/speedtests/powSpeedTest.html
如果您不同意,请尝试http://www.m0ose.com/javascripts/speedtests/powSpeedTest.html 上的程序
回答by IamIC
I just happened to have tested this yesterday, then saw your question now.
我昨天刚好测试了这个,然后现在看到了你的问题。
On my machine, a Core 2 Duo running 1 test thread, it is faster to use multiply up to a factor of 9. At 10, Math.Pow(b, e) is faster.
在我的机器上,Core 2 Duo 运行 1 个测试线程,使用乘法到 9 的速度更快。在 10 时,Math.Pow(b, e) 更快。
However, even at a factor of 2, the results are often not identical. There are rounding errors.
然而,即使是 2 倍,结果往往也不尽相同。存在舍入误差。
Some algorithms are highly sensitive to rounding errors. I had to literally run over a million random tests until I discovered this.
一些算法对舍入误差高度敏感。在我发现这一点之前,我不得不进行了超过一百万次随机测试。
回答by IamIC
Math.Pow(x, y)
is typically calculated internally as Math.Exp(Math.Log(x) * y)
. Evey power equation requires finding a natural log, a multiplication, and raising e
to a power.
Math.Pow(x, y)
通常在内部计算为Math.Exp(Math.Log(x) * y)
。Evey 幂方程需要求自然对数、乘法和乘e
幂。
As I mentioned in my previous answer, only at a power of 10 does Math.Pow()
become faster, but accuracy will be compromised if using a series of multiplications.
正如我在之前的回答中提到的,只有 10 的幂才会Math.Pow()
变得更快,但如果使用一系列乘法,准确性会受到影响。