I'm trying to solve this problem in C# using these 2 approaches:
public double NormalPowerMethod(double x, double toPower)
{
return Math.Pow(x, toPower);
}
public double EfficientPowerMethod(double x, double toPower)
{
return Math.Exp(Math.Log(x) * toPower);
}
I ran a simple test program :
EfficientPower ep = new EfficientPower();
Console.WriteLine("Enter x:");
double x = Double.Parse(Console.ReadLine());
Console.WriteLine("Enter power: ");
int toPower = Int32.Parse(Console.ReadLine());
Stopwatch timer = new Stopwatch();
timer.Start();
Console.WriteLine(string.Format("{0} to the power of {1}= {2}", x,toPower, ep.NormalPowerMethod(x,toPower)));
timer.Stop();
Console.WriteLine("Normal power time =" + timer.ElapsedTicks);
//-------------- efficient
timer.Reset();
timer.Start();
Console.WriteLine(string.Format("Efficient power: {0} to the power of {1}= {2}", x, toPower, ep.EfficientPowerMethod(x, toPower)));
timer.Stop();
Console.WriteLine("Efficient power time =" + timer.ElapsedTicks);
Console.ReadLine();
and I noticed :
Math.pow(x,y) is slower than Math.Exp(Math.log(x) * y) For e.g:
Enter x:
15
Enter power:
26
Normal power: 15 to the power of 26= 3.78767524410635E+30
Normal power time =818
Efficient power: 15 to the power of 26= 3.78767524410634E+30
Efficient power time =533
Enter x:
1024
Enter power:
1024
Normal power: 1024 to the power of 1024= Infinity
Normal power time =810
Efficient power: 1024 to the power of 1024= Infinity
Efficient power time =519
Why such behaviour ? I thought more calculation will be slower ?
Here is the correct measurement script, since we already discusses your measurement is off:
static void Main(string[] args)
{
DateTime start = DateTime.Now;
for (int i = 0; i < 10000000; i++)
{
Math.Pow(10, 100);
}
TimeSpan diff = DateTime.Now - start;
Console.WriteLine("Normal: {0:N0}", diff.TotalMilliseconds);
//-------------- efficient
start = DateTime.Now;
for (int i = 0; i < 10000000; i++)
{
Math.Exp(Math.Log(10) * 100);
}
diff = DateTime.Now - start;
Console.WriteLine("Efficient: {0:N0}", diff.TotalMilliseconds);
Console.ReadLine();
}
The output with 10.000.000 tries (statistics are consistent after numerous tries):
Normal: 1.968 ms.
Efficient: 1.813 ms.
So 'efficient' performs about 8% better.
About the why:
According to Hans Passants answer:
It basically checks for corner cases, then calls the CRT's version of pow().
So there is some, though minor overhead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With