Реализация простого и быстрого возведения в степень на C/C++
Привет всем. Продолжаю потихоньку публиковать свои реализации известных всем и очень популярных алгоритмов, например, уже успел реализовать супер сложную быструю сортировку. На этот раз отклонюсь чуть ближе к математике и рассмотрю алгоритм быстрого возведения в степень, который часто(или даже скорее всегда) используется в стандартных библиотечных функциях возведениях.
Но прежде, чем начать, почему бы не реализовать обычное возведение? Правильно, нет причин себе в этом отказывать, поехали!
Функция возведения числа в степень
Методом «в лоб», пробежимся в цикле и перемножим число само на себя сколько нужно раз. Работает за O(deg) где deg степень.
//Возводит число num в степень deg простым циклом long power(long num, long deg) < long result = 1; for(long i = 0; i < deg; i++) < result *= num; >return result; >
Для возведения по модулю достаточно будет передать этот модуль в функцию и на каждой итерации брать результат по модулю.
Функция возведения числа в отрицательную степень
Небольшое улучшение, добавим возможность возводить число в отрицательную степень. Реализуется легко, изменяем возвращаемое значение и рассматриваем два случая: для положительной степени делаем все как обычно, а для отрицательной возвращаем 1 / result.
//Возводит число num в степень deg простым циклом(степень может быть отрицательной) double power(long num, long deg) < double result = 1; if(deg < 0) < deg = -deg; for(long i = 0; i < deg; i++) < result *= num; >return 1 / result; > else < for (long i = 0; i < deg; i++) < result *= num; >return result; > >
Функция быстрого возведения числа в степень
Ее еще называют бинарным возведением. Алгоритм построен на очевидной формуле
A n = (A n/2 ) 2 = A n/2 * A n/2
То есть для четного n можно получить результат выполнив всего log2n перемножений, что уже дает логарифмическую сложность. А в случае, когда n нечетно, приведем его к четному виду с помощью еще одной очевидной формулы
Реализация выглядит следующим образом.
//Быстрое возведение числа num в степень deg long powerFast(long num, long deg) < long result = 1; while(deg) < if (deg % 2 == 0) < deg /= 2; num *= num; >else < deg--; result *= num; >> return result; >
Функция быстрого возведения в отрицательную степень
Можно реализовать воспользовавшись аналогичным приемом, как и в простом умножении — делим алгоритм на две ветки.
//Быстрое возведение числа num в степень deg(в том числе может быть отрицательной) double powerFast(long num, long deg) < double result = 1; if(deg < 0) < deg = -deg; while(deg) < if (deg % 2 == 0) < deg /= 2; num *= num; >else < deg--; result *= num; >> return 1 / result; > else < while(deg) < if (deg % 2 == 0) < deg /= 2; num *= num; >else < deg--; result *= num; >> return result; > >
Заключение
Таким образом мы научились возводить число в степень с логарифмической скоростью, что пригодится для реализации умножения и деления больших чисел(кстати, сложение и вычитание уже готовы). А на сегодня у меня все, спасибо за внимание!
Как возвести число в степень
((a + b + c)*pi)^2 Как возвести в степень это выражение на языке СИ?
Отслеживать
задан 22 мар 2020 в 15:15
23 3 3 бронзовых знака
Умножить на себя же. Вариант хуже — использовать функцию pow .
22 мар 2020 в 15:17
Чем же плоха функция pow?
22 мар 2020 в 15:17
По нынешним временам для float что умножение, что pow отправляются в сопроцессор с плавающей точкой. А вот что быстрее делается в сопроцессоре с плавающей точкой — умножение или pow это вопрос интересный.
22 мар 2020 в 15:25
Хотя бы потому что в общем случае это вызов функции. Вариант с целочисленной степенью в стандарте вроде бы отсутствует, так что опять же в общем случае это будет вычисление менее эффективное.
Как возвести в степень в c
Во-первых зачем ты цикл используешь вообще не понятно.. Во-вторых твоя программа вылетит сразу после компиляции(сам догадайся почему). В-третьих функцию pow ты не вызовешь с этими аргументами(в VС++).. Юзай либо просто pow(double long x, int y) без никаких циклов, либо эту функцию :
int Pow(int num, int n) < int res = num; for (int i = 1; i < n; i++) < res *= num; >return res; >
a = Pow(2,3) // a == 8
« Когда ты действительно чего-то хочешь, вся Вселенная помогает тебе осуществить твою мечту ».(с) Пауло Коэльо
| fenix-elite |
| Посмотреть профиль |
| Найти ещё сообщения от fenix-elite |
Пользователь
Регистрация: 02.11.2008
Сообщений: 75
Можно сдвигами возводить
for (int i = 1; i < st; i++) a
Где a == 2 и st- степень.
« Когда ты действительно чего-то хочешь, вся Вселенная помогает тебе осуществить твою мечту ».(с) Пауло Коэльо
Последний раз редактировалось fenix-elite; 06.10.2010 в 19:23 .
| fenix-elite |
| Посмотреть профиль |
| Найти ещё сообщения от fenix-elite |
Пользователь
Регистрация: 29.09.2010
Сообщений: 25
Сообщение от fenix-elite
Во-первых зачем ты цикл используешь вообще не понятно.. Во-вторых твоя программа вылетит сразу после компиляции(сам догадайся почему). В-третьих функцию pow ты не вызовешь с этими аргументами(в VС++).. Юзай либо просто pow(double long x, int y) без никаких циклов, либо эту функцию :
int Pow(int num, int n) < int res = num; for (int i = 1; i < n; i++) < res *= num; >return res; >
a = Pow(2,3) // a == 8
Задание такое. Как ни странно у меня этот код отлично работает (естественно только для целых чисел). Если вы имеете ввиду ту ошибку что я не присвоил значение переменной N, то это можно сделать для проверки цикла. Все работает. Только что проверил. В чем моя ошибка? Pow работает если подключить соответствующую библиотеку
Форумчанин
Регистрация: 05.12.2009
Сообщений: 253
Если изучаешь циклы то и возводить в степень нужно с помощью цикла.
int i,N,a; a=2;//Возводимое в степень число cin>>N; // Cтепень возведения for(i=1;i<=N-1;i++) a*=2; cout<
Приходится бежать со всех ног, чтобы только остаться на том же месте! Если хочешь попасть в другое место, тогда нужно бежать по меньшей мере вдвое быстрее! Льюис Кэрол
Пользователь
Регистрация: 29.09.2010
Сообщений: 25
Сообщение от atenon
Если изучаешь циклы то и возводить в степень нужно с помощью цикла.
int i,N,a; a=2;//Возводимое в степень число cin>>N; // Cтепень возведения for(i=1;i<=N-1;i++) a*=2; cout<
И какой должен быть ответ в вашем коде, если степень возведения равна 2 (N=2) .
Получается -171798692 = )))
а должно быть 4
Последний раз редактировалось Marmelade; 07.10.2010 в 14:10 .
Форумчанин
Регистрация: 05.12.2009
Сообщений: 253
Неа логика железобетоная 2х2=4 было есть и вроде никто не планировал отменять, цикл выполняется один раз следовательно "а"(то есть 2) умножается на 2 один раз в итоге получается 4. Может быть вы не инициализировали переменную "а"?
Приходится бежать со всех ног, чтобы только остаться на том же месте! Если хочешь попасть в другое место, тогда нужно бежать по меньшей мере вдвое быстрее! Льюис Кэрол
Как на языке Си возвести число в степень?
Как я понимаю, пишется подобным образом:
float f (float x) < return 3*(-x)+4*x-2; >
только в данном случае 3 умножается на -x.
Каким образом правильно написать, чтобы число три было в степени -x?
Лучший ответ
Можно вроде так: pow(x,y). Тут x - основание степени, y - показатель. Можно заключать их в скобки (если отрицательные)
Остальные ответы
Почитай лучше справочник функций, а то тебе щас тут напишут.
Максим ЯковлевГуру (3502) 15 лет назад
Sea_hawkГуру (3486) 15 лет назад
А Вы не можете функцию подсказать? Я думаю, возведение в степень должно быть просто, вот только не сталкивался с этим.
А справочника функций нет.
Svt Мастер (2256) Не знаю конечно язык С++, но элементарно, присвой вводимой переменной "х", отрицательное значение, заведомо и все на этом. Вопрос в том, где эта переменная еще учавствует