Возведение в степень с плавающей точкой без степенной функции - PullRequest
9 голосов
/ 19 августа 2010

В настоящее время я должен работать в среде, где оператор питания прослушивается.Может кто-нибудь придумать способ временно обойти эту ошибку и вычислить a ^ b (с плавающей запятой) без функции или оператора степени?

Ответы [ 3 ]

23 голосов
/ 19 августа 2010

, если у вас есть sqrt ():

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 ); }

тестовый код:

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;
}

выходы:

3.40835049344
3.40835206431
2.71882549461
2.71882549383
393371.348073
393371.212573
1.00011529225
1.00011513588
1.00000548981
1.00000115129
9 голосов
/ 19 августа 2010

Вы можете использовать идентификатор a b = e ( b log a ) , тогда все вычисления относятся к одной и той же базе e = 2.71828 ...

Теперь вам нужно реализовать f (x) = ln (x) и g (x) = e ^ x. Быстрый метод с низкой точностью - использовать таблицы поиска для f (x) и g (x). Может быть, этого достаточно для ваших целей. Если нет, вы можете использовать расширения серии Тейлора , чтобы выразить ln (x) и e ^ x в терминах умножения и сложения.

3 голосов
/ 10 октября 2011

, учитывая, что вы можете использовать sqrt, этот простой рекурсивный алгоритм работает:

Предположим, что мы вычисляем aˆb. Алгоритм работает, выполняя Быстрое Возведение в степень для экспоненты, пока мы не дойдем до дробной части, один раз в дробной части, сделаем модифицированный двоичный поиск, пока мы не будем достаточно близки к дробной части.

double EPS = 0.0001;

double exponentiation(double base, double exp){
  if(exp >= 1){
    double temp = exponentiation(base, exp / 2);
    return temp * temp;
  } else{
    double low = 0;
    double high = 1.0;

    double sqr = sqrt(base);
    double acc = sqr;    
    double mid = high / 2;

    while(abs(mid - exp) > EPS){
      sqr = sqrt(sqr);

      if (mid <= exp) {
          low = mid;
          acc *= sqr;
      } else{
          high = mid;
          acc *= (1/sqr);
      }

      mid = (low + high) / 2;
    }

    return acc;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...