Язык Си в примерах/Степень числа: различия между версиями

Материал из Викиучебника — открытых книг для открытого мира
Содержимое удалено Содержимое добавлено
Поставил теги <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

Язык Си в примерах


  1. Компиляция программ
  2. Простейшая программа «Hello World»
  3. Учимся складывать
  4. Максимум
  5. Таблица умножения
  6. ASCII-коды символов
  7. Верхний регистр
  8. Скобочки
  9. Факториал
  10. Степень числа
  11. Треугольник Паскаля
  12. Корень уравнения
  13. Система счисления
  14. Сортировка
  15. Библиотека complex
  16. Сортировка на основе qsort
  17. RPN-калькулятор
  18. RPN-калькулятор на Bison
  19. Простая грамматика
  20. Задача «Расчёт сопротивления схемы»
  21. Простая реализация конечного автомата
  22. Использование аргументов командной строки
  23. Чтение и печать без использования stdio
  24. Декодирование звукозаписи в формате ADX
  25. Другие примеры

Для вычисления функции есть рекуррентная формула:


Вот программа, которая основана на этой формуле:

 /* 
   Степень числа: простая рекурсия
 */
 
 #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.