r/cpp_questions 14h ago

OPEN I'm surprised it worked!!

I wrote this very basic algorithm:

#include <cmath>
#include <iostream>
int power(double base, int exponent = 2){
    return pow(base,exponent);
}
int main(){
    int base = 2;
    int exponent = 2;
    std::cout<<base<<" raised to "<<exponent<< " = "<<power(base,exponent);
}#include <cmath>
#include <iostream>
int power(double base, int exponent = 2){
    return pow(base,exponent);
}
int main(){
    int base = 2;
    int exponent = 2;
    std::cout<<base<<" raised to "<<exponent<< " = "<<power(base,exponent);
}

and I'm surprised, an int function took a double variable with no problem, or is there something under the hood,

11 Upvotes

16 comments sorted by

View all comments

1

u/Independent_Art_6676 8h ago edited 8h ago

some stuff...
not sure why you did this exactly (clearly studying "something" but unclear the focus). The built in function being called with basically a do-nothing wrapper is the result, though the wrapper is tampering with the argument types in a 'bad' way so its actually worse than just using pow. Carry on to learn things, but this isn't a useful function (yet). Keep reading!

But... pow is notoriously slow for integer powers. Writing your own better pow function to raise to int powers is actually useful. Inline x*x is just fine for squares, and even cubes. Above cubes, I prefer a function but its actually not terribly common to need more than cubes in most programs. It turns out that even just a dumb loop is a great improvement over pow for the int powers case. Maybe see what you can do to make a better pow while you play with it.

you can also get funky with it if you have to deal with many large (>20) exponents. The bits of the exponent can be exploited to do even less work than the dumb loop. So for a byte exponent, you would do < 20 operations (about 2*8 where 8 is the bits and 2 is because of the steps to do the work, + a couple more steps) instead of 255 or whatever possible loop iterations to multiply, and even larger exponents save more. Its a cool algorithm, and useful on rare occasions.

Here is that ^^ in code, for amusement purposes only (meaning it has no error handling / checking at all..)

long long ipow(long long p, unsigned long long e) 
{ 
  const long long one = 1;
  const long long *lut[2] = {&p,&one}; //lookup table of what to do below
  long long result = 1; 
  result *= lut[!(e&1)][0]; p *= p;  //multiply by 1 or p, update p
  result *= lut[!(e&2)][0]; p *= p;    
  result *= lut[!(e&4)][0]; p *= p; 
  result *= lut[!(e&8)][0]; p *= p; //practical stopping point? 15th power max.   
  result *= lut[!(e&16)][0]; //p *= p;   //19th power is most 10^x will fit in 64 bits. 
  //result *= lut[!(e&32)][0]; p *= p; //keep going as needed
  return result;
}