24

I need to compute power (10, n)

Is it OK to use Math.Pow (10, n)?

Or should I use a loop?

for (int i = 0; i < n; i++){
  x*=10;
}

Which one is better? and why?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
user380719
  • 9,663
  • 15
  • 54
  • 89
  • 8
    Why would you think that `Math.Pow` is *not* ok? – Kirk Woll Oct 23 '10 at 16:42
  • Would you use a loop to add 10 n times, or would you just use 10 * n? :-) – CesarGon Oct 23 '10 at 16:43
  • 4
    I do not know .NET, but the OP is probably concerned about the fact that Pow takes a float and returns a float, when he could do with just integers (if n is not too large). – Andreas Rejbrand Oct 23 '10 at 16:43
  • 2
    correct, I am concerned about floats. – user380719 Oct 23 '10 at 16:44
  • 3
    @Andreas, but float math is not slow. And float math with integers loses no precision. – Kirk Woll Oct 23 '10 at 16:45
  • 1
    If you're concerned about performance, measure it. If not, use Math.Pow. – arx Oct 23 '10 at 16:57
  • You have to remember that it is unlikely that Math.Pow is equivalent to your trivial implementation (for example see http://www.netlib.org/fdlibm/e_pow.c which does not use any looping constructs, although the code is shocking :P). For small powers you are almost certainly better off using a loop. Still don't forget that Math.Pow also implements fractional powers and negative powers which clearly your code wouldn't handle. It depends what you are trying to do. If all else fails, PROFILE! :) – tyranid Oct 23 '10 at 18:17
  • 2
    @KirkWoll `float` math with integers loses precision as soon as the integers involved are bigger than 2^24, because a `float` has only 24 bit of mantissa. – Gunther Piez Nov 16 '12 at 08:34
  • The concern is that Math.Pow() might give a result very close to the intended integral, and that the decimal part gets lopped off in casting. However, as these are all powers of 10 I tested, and it gives the integral value all the way until long has an arithmetic overflow. – NameSpace Mar 14 '23 at 04:04

8 Answers8

13

Math.Pow is better.
Here's a rule of thumb - in 99% of the scenarios, favor built-in functions over custom implementations. This makes your code clearer, saves you lots of work, and reduce chances for errors.

Only when you think of using built-in functions in ways they weren't meant to be used, or when they have severe latency problems (never encountered these scenarios myself, to be honest), should you consider building your own implementation.

Oren A
  • 5,870
  • 6
  • 43
  • 64
10

If both base and exponent are integers you might consider not using Pow. But even in that case Pow is usually better because its more readable. If at least one is a floatingpoint value, use Pow.

If the exponent is 0.5 you should use Sqrt, and if the exponent is a small integer (2,3,4) expressing the formula with multiplications is faster, but less readable.

If you want to implement fast exponentiation with an integer exponent the Square-and-Multiply algorithm and not a simple loop might be what you want. But in most scenarios Pow is still faster.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
8

For integers, maybe a for loop is faster than Math.Pow which probably deals with floating-point numbers. But I seriously doubt that the difference is significant in your case (even though I do not know it).

But if you work with 32-bit signed integers, then you can only store the values of 10^n for n <= 9. But then you would gain speed (and maybe readability) by storing these nine (ten) powers of ten in an array. This is not hard: they are (1), 10, 100, 1000, ... .

If you need to compute 10^n for larger n, you do need to use floating-point numbers. And then there is no reason whatsoever not to use Math.Pow. This is as fast as it gets, and easily readable.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
  • Anyhow: a modern computer can do (tens of) millions of floating-points exponentiations per second, so unless you are doing some really tight loops in an advanced 3D game or sth, performance wouldn't be an issue... – Andreas Rejbrand Oct 23 '10 at 16:56
  • 1
    +1 for using a lookup - surely quickest if `n <= 9` (as it must be for an `int` to hold the result) – AakashM Oct 23 '10 at 18:04
4

Depends on which one communicates "10 to the power of n" more clearly.

In my case, Math.Pow(10, n) (although it could mean math, collectively, punching 10 and n in their faces as well, I dunno).

It's similar to how I'd rather algebraically express "10 to the power of n" as 10^n (or 10n) than 10 * 10 * 10 * ... * 10 n times, especially given that n is variable.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
3

The answer would normally be yes, use Math.Pow().

However: if this code is really time-critical and you know you're dealing with small powers 1-9 so the result can be expressed in an Int32 then it can be worth optimizing. I just made a quick test-app and profiled the two versions (making sure the compiler hadn't optimized any code away) and the result on my laptop for the worst-case of 10^9 was that the loop was 20 times faster than Math.Pow(10,9).

But please remember, maybe this calculation is not really a bottleneck after all. If you know for a fact that it is, e.g. if you've profiled your app and found it to be a real problem, then go ahead and replace it with a loop-based method (or even better, an array-lookup). If you're merely guessing that it may a problem then I would suggest you stick to Math.Pow. In general: only optimize code that you know is a performance bottleneck.

1

Math.Pow is provided for you, and well documented.

Any gotchas are in the documentation.

Why would you not want to use a provided function?

abelenky
  • 63,815
  • 23
  • 109
  • 159
0

Yes, it is OK to use Math.Pow().

Echilon
  • 10,064
  • 33
  • 131
  • 217
ika
  • 1,889
  • 2
  • 12
  • 9
0

There are way more performant implementations of integer Pow, than multiplying by 10 in a loop.

See this answer, for example, it also works for other base values, not just 10.

Also, consider caching results, up until a reasonable amount, in an array.

Here's my recent code, for a reference:

private static readonly Int64[] PowBase10Cache = {
    1,
    10,
    100,
    1000,
    10000,
    100000,
    1000000,
    10000000,
    100000000,
    1000000000,
    10000000000,
    100000000000,
    1000000000000,
    10000000000000,
    100000000000000,
    1000000000000000,
    10000000000000000,
    100000000000000000,
    1000000000000000000,
    };

public static Int64 IPowBase10(int exp)
{
    return exp < PowBase10Cache.Length ? PowBase10Cache[exp] : IPow(10L, exp);
}

public static Int64 IPow(Int64 baseVal, int exp)
{
    Int64 result = 1;
    while (exp > 0)
    {
        if ((exp & 1) != 0)
        {
            result *= baseVal;
        }
        exp >>= 1;
        baseVal *= baseVal;
    }
    return result;
}
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
YB_Evil
  • 123
  • 1
  • 6