Язык Си в примерах/Степень числа: различия между версиями
Содержимое удалено Содержимое добавлено
Поставил теги <source> |
исправление |
||
Строка 16: | Строка 16: | ||
double power(double x, long n) { |
double power(double x, long n) { |
||
if(n == 0) return 1; |
if(n == 0) return 1; |
||
if(n < 0) return power ( 1.0 / x, -n); |
if(n < 0) return power ( 1.0 / x, --n); |
||
return x * power(x, n - 1); |
return x * power(x, n - 1); |
||
} |
} |
||
Строка 51: | Строка 51: | ||
double tmp; |
double tmp; |
||
if(n == 0) return 1; |
if(n == 0) return 1; |
||
if(n < 0) return power ( 1 / x, -n); |
if(n < 0) return power ( 1 / x, --n); |
||
if(n % 2) return x * power (x, n - 1); |
if(n % 2) return x * power (x, n - 1); |
||
return power(x * x, n / 2); |
return power(x * x, n / 2); |
||
Строка 78: | Строка 78: | ||
</source> |
</source> |
||
* Сколько шагов требуется для вычисления <math>a^{30}\,\!</math> вторым |
* Сколько шагов требуется для вычисления <math>a^{30}\,\!</math> вторым методом. |
||
* Покажите, что второй алгоритм выполняется за логарифмическое по n число шагов, а точнее ограничено сверху <math>2\cdot \log_2 n\,\!</math> (еще точнее: в точности равно числу знаков в двоичной записи числа n плюс число единичек в этой записи). |
* Покажите, что второй алгоритм выполняется за логарифмическое по n число шагов, а точнее ограничено сверху <math>2\cdot \log_2 n\,\!</math> (еще точнее: в точности равно числу знаков в двоичной записи числа n плюс число единичек в этой записи). |
||
* Объясните, как работает программа 3. |
* Объясните, как работает программа 3. |
Версия от 09:43, 4 июля 2008
- Компиляция программ
- Простейшая программа «Hello World»
- Учимся складывать
- Максимум
- Таблица умножения
- ASCII-коды символов
- Верхний регистр
- Скобочки
- Факториал
- Степень числа
- Треугольник Паскаля
- Корень уравнения
- Система счисления
- Сортировка
- Библиотека complex
- Сортировка на основе qsort
- RPN-калькулятор
- RPN-калькулятор на Bison
- Простая грамматика
- Задача «Расчёт сопротивления схемы»
- Простая реализация конечного автомата
- Использование аргументов командной строки
- Чтение и печать без использования stdio
- Декодирование звукозаписи в формате ADX
- Другие примеры
Для вычисления функции есть рекуррентная формула:
Вот программа, которая основана на этой формуле:
/*
Степень числа: простая рекурсия
*/
#include<stdio.h>
double power(double x, long n) {
if(n == 0) return 1;
if(n < 0) return power ( 1.0 / x, --n);
return x * power(x, n - 1);
}
void main() {
double x;
long n;
while (scanf ("%lf %ld", &x, &n) == 2) {
printf("%lf\n", power (x, n));
}
}
Но есть более «умная» рекурсивная функция:
Например, если обозначть стрелочкой слово «сводится к », то при вычислении для первой рекурсии получим цепочку длины 12:
А для второй рекурсии цепочку из 5 шагов:
Для больших n разница в длине цепочки более разительная. В частности первой рекурсией вычисляется за 10000 шагов, а второй -- за 19 шагов.
/*
Программа 2: степень числа -- оптимизированная рекурсия.
*/
double power(double x, long n)
{
double tmp;
if(n == 0) return 1;
if(n < 0) return power ( 1 / x, --n);
if(n % 2) return x * power (x, n - 1);
return power(x * x, n / 2);
}
/*
Программа 3: cтепень числа -- оптимальный алгоритм без рекурсии.
*/
double power(double x, long n)
{
double a = 1;
while(n) {
if(n % 2) {
a *= x;
n--;
}
else{
x *= x;
n /= 2;
}
}
return a;
}
- Сколько шагов требуется для вычисления вторым методом.
- Покажите, что второй алгоритм выполняется за логарифмическое по n число шагов, а точнее ограничено сверху (еще точнее: в точности равно числу знаков в двоичной записи числа n плюс число единичек в этой записи).
- Объясните, как работает программа 3.