Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Центр помощи > [C++] Функция возведения в степень


Автор: Kernigan 18.6.2006, 15:06
Требуется написать функцию, на C++, возведения в степень y основания x, где x, y - тип класса, например, MyClass pow (MyClass & x, MyClass & y). Если кто-то уже сталкивался с подобной задачей, прошу откликнуться. 

Автор: MAKCim 18.6.2006, 22:10
реализуй умножение больших чисел (возьми исходник) 

Автор: Kernigan 18.6.2006, 22:21
В инете я нашёл несколько исходников, но ничего конкретного. Если у вас MAKCim есть ссылка что-то похожее, укажите пожалуйста. 

Автор: MAKCim 18.6.2006, 23:10
Код

template<class T> 
    class long_number
{
public:
    typedef T char_t;
private:
    std::vector<char_t> number_;
public:
    long_number<T>& operator*=(const long_number<T>&);

    long_number<T>& operator--();

    bool operator>(long);
};

template<class T> long_number<T> operator^
    (const long_number<T>& obj_a, const long_number<T> obj_b)
{
    long_number<T> obj=obj_a, deg=obj_b;
    while (--deg>0) obj*=obj_a;
    return obj;
}

реализуй операции operator*=, --, > 

Автор: Kernigan 21.6.2006, 21:58
Благодарю MAKSim'а за предоставленный код 

Автор: En_t_end 26.1.2007, 18:42
MAKCim, 
А ускорить процесс возведения в степень можно как-то ?

Автор: V.A.KeRneL 27.1.2007, 10:14
Цитата(En_t_end @  26.1.2007, 18:42 Найти цитируемый пост)

MAKCim, 
А ускорить процесс возведения в степень можно как-то ?


En_t_end, а можно я отвечу? Ну, пожалуйста! smile

Из книжки Ксиены и Ревиллы: 
«* Возведение в степень. Возведение в степень — это повторяемое умножение, так что тут возникают те же проблемы с производительностью, что и при многократном сложении длинных чисел. Хитрость состоит в том, чтобы заметить, что 
Код

a^n = a^(n div 2) * a^(n div 2) * a^(n mod 2)

, так что можно обойтись, используя только логарифмическое число умножений.»

Автор: sergejzr 27.1.2007, 14:08
Цитата(V.A.KeRneL @  27.1.2007,  09:14 Найти цитируемый пост)
так что можно обойтись, используя только логарифмическое число умножений.»

V.A.KeRneL, добавлю немного кода с пояснением мелочей smile

bas^pot=power(bas,pot)
Код

int power (int bas, int pot) {
//В надежде на то, что компилер соптимирует pot%2 на pot&1 и pot /= 2 на pot>>1.
  int p = 1;
  while (pot > 0) { 
    if (pot%2) { p = p * bas ; }
    bas = bas  * bas ;
    pot / =2;
  }
  return p;
}

Если pot постоянный для нескольких чисел, то можно один раз просто разбить его на биты и вместо pot%2 проверять, имеет бит значение 1, или 0.

Код

int main()
{
int bas[]{123,34,546,678};
int pot=98;
int bitmasklength;
int *potmask=toBitmask(pot,&bitmasklength);

for(int i=0;i<sizeof(bas);i++)
{
printf("%i^%i=%i\n",bas[i],pot,power (bas, potmask,bitmasklength));
}
delete potmask;
}
int power (int bas, int *potmask,int potmasklength) {
  int p = 1;
  for (int i=0;i<potmasklength;i++) { 
    if (pot[i]) { p = p * bas ; }
    bas = bas  * bas ;
  }
  return p;
}

int*potmask(int pot, int*length)
{
int *newmask=new int[32]; //максималъно 32 бита у нас тут
int i=0;
while (pot > 0) { 
    newmask[i]=pot%2
 
    pot / =2;i++;
  }
*length=i;
return newmask;
}



Если необходимо работать по модулю какого-то числа (n), то в цикле надо просто это (%n) вписать после каждого умножения

PS: Код к сожалению проверить не было возможности. Написан "на коленке"
PPS: Вобще-то эти способы (для умножения, степени, проверки на простоту) разработал http://ru.wikipedia.org/wiki/%D0%9B%D0%B0%D0%B3%D1%80%D0%B0%D0%BD%D0%B6%2C_%D0%96%D0%BE%D0%B7%D0%B5%D1%84_%D0%9B%D1%83%D0%B8 
Хотя быстрое умножение было известно ещё в древнем Египте.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)