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

Материал из testwiki
Версия от 17:31, 4 марта 2024; imported>1234qwer1234qwer4 (1234qwer1234qwer4 переименовал страницу Обсуждение модуля:Язык Си в примерах/Степень числа в Язык Си в примерах/Степень числа поверх перенаправления и без оставления перенаправления: возврат)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигации Перейти к поиску

Шаблон:Содержание «Язык Си в примерах»

Для вычисления функции f(n)=an есть рекуррентная формула:

an=aan1,a0=1.

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

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

Приведёный выше пример не будет работать для отрицательных показателей степени (см. третью строку функции "power"). Правильнее было бы так:

 /* 
   Степень числа: простая рекурсия
 */
 
 #include<stdio.h>

 double power(double x, long n) {
    if(n == 0) return 1.0;
    if(n < 0) return 1.0 / (x * power (1.0 / x, n + 1));
    return x * power(x, n - 1);
 }

 void main() {
     double x;
     long n;
     while (scanf ("%lf %ld", &x, &n) == 2) {
        printf("%16.16lf\n", power (x, n));
     }
 }

Но есть более «умная» рекурсивная функция: an={aan1,if n is odd(an/2)2,if n is even

Например, если обозначить стрелочкой слово «сводится к », то при вычислении a12 для первой рекурсии получим цепочку длины 12:

a12a11a10a9a8a7a6a5a4a3a2a1a0.

А для второй рекурсии цепочку из 5 шагов: a12a6a3a2a1a0.

Для больших n разница в длине цепочки более разительная. В частности a10000 первой рекурсией вычисляется за 10000 шагов, а второй -- за 19 шагов.

 /*
  Программа 2: степень числа -- оптимизированная рекурсия.
 */
 double power(double x, long n)
 {
    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;
 }
  • Напишите программу, вычисляющую double в степени double.
  • Сколько шагов требуется для вычисления a30 вторым методом?
  • Покажите, что второй алгоритм выполняется за логарифмическое по n число шагов, а точнее ограничено сверху 2log2n (еще точнее: в точности равно числу знаков в двоичной записи числа n плюс число единичек в этой записи).
  • Объясните, как работает программа 3.

Шаблон:BookCat