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

后端 未结 12 867
逝去的感伤
逝去的感伤 2020-12-05 13:25

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-forw

12条回答
  •  情歌与酒
    2020-12-05 13:44

    Based on Mats Petersson approach, but compile time generation of cache.

    #include 
    #include 
    #include 
    
    // digits
    
    template 
    constexpr T digits(T number) {    
      return number == 0 ? 0 
                         : 1 + digits(number / 10);
    }
    
    // pow
    
    // https://stackoverflow.com/questions/24656212/why-does-gcc-complain-error-type-intt-of-template-argument-0-depends-on-a
    // unfortunatly we can't write `template ` because of partial specialization `PowerOfTen`
    
    template 
    struct PowerOfTen {
      enum { value = 10 * PowerOfTen::value };
    };
    
    template 
    struct PowerOfTen {
      enum { value = 1 };
    };
    
    // sequence
    
    template
    struct pow10_sequence { };
    
    template
    struct make_pow10_sequence_from 
    : make_pow10_sequence_from { 
      //  
    };
    
    template
    struct make_pow10_sequence_from 
    : pow10_sequence { 
      //
    };
    
    // base10list
    
    template 
    constexpr std::array base10list(pow10_sequence) {
      return {{ PowerOfTen::value... }};
    }
    
    template 
    constexpr std::array base10list() {    
      return base10list(make_pow10_sequence_from());
    }
    
    template 
    constexpr std::array::max())> base10list() {    
      return base10list::max())>();    
    };
    
    // main pow function
    
    template 
    static T template_quick_pow10(T n) {
    
      static auto values = base10list();
      return values[n]; 
    }
    
    // client code
    
    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] == 't') {
    
        for(long i = 0; i < outer_loops / n; i++) {
    
          for(int j = 1; j < n+1; j++) {
    
            sum += template_quick_pow10(n);
          }
        }
      }
    
      std::cout << "sum=" << sum << std::endl;
      return 0;
    }
    

    Code does not contain quick_pow10, integer_pow, opt_int_pow for better readability, but tests done with them in the code.

    Compiled with gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5), using -Wall -O2 -std=c++0x, gives the following results:

    $ g++ -Wall -O2 -std=c++0x main.cpp
    
    $ time ./a.out  8 a
    sum=100000000000000000
    
    real  0m0.438s
    user  0m0.432s
    sys 0m0.008s
    
    $ time ./a.out  8 b
    sum=100000000000000000
    
    real  0m8.783s
    user  0m8.777s
    sys 0m0.004s
    
    $ time ./a.out  8 c
    sum=100000000000000000
    
    real  0m6.708s
    user  0m6.700s
    sys 0m0.004s
    
    $ time ./a.out  8 t
    sum=100000000000000000
    
    real  0m0.439s
    user  0m0.436s
    sys 0m0.000s
    

提交回复
热议问题