c++numerical

Any way faster than pow() to compute an integer power of 10 in C++?


I know power of 2 can be implemented using << operator. What about power of 10? Like 10^5? Is there any way faster than pow(10,5) in C++? It is a pretty straight-forward computation by hand. But seems not easy for computers due to binary representation of the numbers... Let us assume I am only interested in integer powers, 10^n, where n is an integer.


Solution

  • Something like this:

    int quick_pow10(int n)
    {
        static int pow10[10] = {
            1, 10, 100, 1000, 10000, 
            100000, 1000000, 10000000, 100000000, 1000000000
        };
    
        return pow10[n]; 
    }
    

    Obviously, can do the same thing for long long.

    This should be several times faster than any competing method. However, it is quite limited if you have lots of bases (although the number of values goes down quite dramatically with larger bases), so if there isn't a huge number of combinations, it's still doable.

    As a comparison:

    #include <iostream>
    #include <cstdlib>
    #include <cmath>
    
    static int quick_pow10(int n)
    {
        static int pow10[10] = {
            1, 10, 100, 1000, 10000, 
            100000, 1000000, 10000000, 100000000, 1000000000
        };
    
        return pow10[n]; 
    }
    
    static int integer_pow(int x, int n)
    {
        int r = 1;
        while (n--)
           r *= x;
    
        return r; 
    }
    
    static int opt_int_pow(int n)
    {
        int r = 1;
        const int x = 10;
        while (n)
        {
            if (n & 1) 
            {
               r *= x;
               n--;
            }
            else
            {
                r *= x * x;
                n -= 2;
            }
        }
    
        return r; 
    }
    
    
    int main(int argc, char **argv)
    {
        long long sum = 0;
        int n = strtol(argv[1], 0, 0);
        const long outer_loops = 1000000000;
    
        if (argv[2][0] == 'a')
        {
            for(long i = 0; i < outer_loops / n; i++)
            {
                for(int j = 1; j < n+1; j++)
                {
                    sum += quick_pow10(n);
                }
            }
        }
        if (argv[2][0] == 'b')
        {
            for(long i = 0; i < outer_loops / n; i++)
            {
                for(int j = 1; j < n+1; j++)
                {
                    sum += integer_pow(10,n);
                }
            }
        }
    
        if (argv[2][0] == 'c')
        {
            for(long i = 0; i < outer_loops / n; i++)
            {
                for(int j = 1; j < n+1; j++)
                {
                    sum += opt_int_pow(n);
                }
            }
        }
    
        std::cout << "sum=" << sum << std::endl;
        return 0;
    }
    

    Compiled with g++ 4.6.3, using -Wall -O2 -std=c++0x, gives the following results:

    $ g++ -Wall -O2 -std=c++0x pow.cpp
    $ time ./a.out 8 a
    sum=100000000000000000
    
    real    0m0.124s
    user    0m0.119s
    sys 0m0.004s
    $ time ./a.out 8 b
    sum=100000000000000000
    
    real    0m7.502s
    user    0m7.482s
    sys 0m0.003s
    
    $ time ./a.out 8 c
    sum=100000000000000000
    
    real    0m6.098s
    user    0m6.077s
    sys 0m0.002s
    

    (I did have an option for using pow as well, but it took 1m22.56s when I first tried it, so I removed it when I decided to have optimised loop variant)