Currently I have to work in an environment where the power-operator is bugged. Can anyone think of a method temporarily work around this bug and compute a^b (both floating point) without a power function or operator?
+6
A:
You can use the identity ab = e(b log a), then all the calculations are relative to the same base e = 2.71828...
Now you have to implement f(x) = ln(x), and g(x) = e^x. The fast, low precision method would be to use lookup tables for f(x) and g(x). Maybe that's good enough for your purposes. If not, you can use the Taylor series expansions to express ln(x) and e^x in terms of multiplication and addition.
Jim Lewis
2010-08-19 05:46:34
i have a working ln function. However, for the Taylor series I need powers again.
ymihere
2010-08-19 06:28:46
@ymihere: The Taylor series expansion only contains integer exponents, which can be reduced to multiplication.
Jim Lewis
2010-08-19 06:41:17
@ymihere: do you have exp() available? if so, this solution is best!
Tom Sirgedas
2010-08-19 15:29:54
@tom: i don't have exp. actually, that's what I am working around.
ymihere
2010-08-20 08:32:15
+6
A:
if you have sqrt() available:
double sqr( double x ) { return x * x; }
// meaning of 'precision': the returned answer should be base^x, where
// x is in [power-precision/2,power+precision/2]
double mypow( double base, double power, double precision )
{
if ( power < 0 ) return 1 / mypow( base, -power, precision );
if ( power >= 10 ) return sqr( mypow( base, power/2, precision/2 ) );
if ( power >= 1 ) return base * mypow( base, power-1, precision );
if ( precision >= 1 ) return sqrt( base );
return sqrt( mypow( base, power*2, precision*2 ) );
}
double mypow( double base, double power ) { return mypow( base, power, .000001 ); }
test code:
void main()
{
cout.precision( 12 );
cout << mypow( 2.7, 1.23456 ) << endl;
cout << pow ( 2.7, 1.23456 ) << endl;
cout << mypow( 1.001, 1000.7 ) << endl;
cout << pow ( 1.001, 1000.7 ) << endl;
cout << mypow( .3, -10.7 ) << endl;
cout << pow ( .3, -10.7 ) << endl;
cout << mypow( 100000, .00001 ) << endl;
cout << pow ( 100000, .00001 ) << endl;
cout << mypow( 100000, .0000001 ) << endl;
cout << pow ( 100000, .0000001 ) << endl;
}
outputs:
3.40835049344
3.40835206431
2.71882549461
2.71882549383
393371.348073
393371.212573
1.00011529225
1.00011513588
1.00000548981
1.00000115129
Tom Sirgedas
2010-08-19 06:34:28
thanks alot. this is precisely was what i was looking for. Out of interest: can you give me any background to that algorithm?
ymihere
2010-08-19 07:40:55
Sure, the basic idea is that x^.5 = sqrt(x), x^.25 = sqrt(sqrt(x)), x^.125 = sqrt(sqrt(sqrt(x))), etc. With these building blocks, we can say x^.625 = (x^.5)*(x^.125). We can't express, say, x^.3 exactly, but we can get arbitrarily close. I implemented this a little differently, but it uses the same concept.
Tom Sirgedas
2010-08-19 15:28:17