2016-02-18 9 views
-6

Я реализовал свою собственную функцию мощности, которую я еще использовал для вычисления корня. Я хотел сравнить результат, возвращенный моей функцией, с той, которая возвращается функцией pow, из math.h. Однако оказалось, что при использовании моей силовой функции для вычисления корней она дает неправильные ответы. Квадратный корень из 15 составляет около 3, но мой код печатает 15:Почему моя собственная функция мощности, когда используется для вычисления корней, возвращает неправильный результат?

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <math.h> 

double power(int base, double index) 
{ 
    double result = 1; 
    int i; 

    for (i = 0; i<index; i++) 
     result *= base; 

    return result; 
} 

int main() 
{ 
    int n = 15, s = 2; 

    printf("2^3 = %f\n\n", power(2,3)); 

    double result1 = power(n, 1.0/s); 
    printf("%d\n", (int)result1); 

    double result2 = pow(n, 1.0/s); 
    printf("%d\n", (int)result2); 

    return 0; 
} 
+5

Это не проблема с кодированием, а скорее алгоритмическая. Алгоритм, который вы использовали для 'power', работает только для целочисленного' index'. –

+0

На уровне механизма это потому, что для базы 1 и показателя 1/2, то, что вы делаете, просто умножается на 1 на 1, а затем возвращает это в результате. На уровне математики это просто потому, что вы не вычисляете такой квадратный корень. –

+0

@R_Kapp: Изменение 'int' на' double' не решает проблему, теперь ответ 15 – darias

ответ

1

Ваша функция не работает, потому что его реализация использует метод, который обычно используется для объяснения способности интуитивно ("взять номер 1 и умножить его exponent раз base "). Однако этот метод применим только для натуральных чисел. Это не фактическое математическое определение степеней с произвольными показателями.

Если вы хотите иметь функцию, которая работает для других числовых пространств, вам необходимо find a numerical method that's applicable for those those as well. Как правило, они включают вычисление определенной серии.

Во-первых, вам необходимо определить функцию, которая обрабатывает эти:

  1. мощность для показателей, которые являются положительными целыми числами. (Это то, что вы достигли.)
  2. Мощность для экспонентов, которые являются отрицательными целыми числами. (Вы можете использовать инверсию, abs и ваш предыдущий шаг для этого.)
  3. Мощность для экспоненты равна нулю. (К счастью, это просто константа для большинства случаев.)

Вы также будете нуждаться в уже реализуемый ln(double x) (или вы можете реализовать его путем суммирования конкретного ряда, который будет включать вашу функцию питания целое) и factorial(int n) (это легко написать, даже интуитивно).

Затем вы можете написать функцию, которая принимает любую реальную base, и любой реальный exponent и целое n и сделать это:

  1. Вычислить exponent * ln(base).
  2. Используйте функцию целочисленной мощности для вычисления n-й степени этого результата.
  3. Разделите этот результат на factorial(n).

Обертка это в цикле, который не суммирует результаты этого вычисления для всех значений n от 0 вплоть до самого высокого, которые могут быть обработаны надлежащим образом и эффективно (чем выше максимальная n, тем лучше приближение). Эта сумма представляет собой математический результат, который вы ищете. Поэтому функция, которая принимает base и exponent в качестве параметров и запускает вышеупомянутый цикл для ряда значений n, является вашей фактической конечной функцией pow, которую вы можете открыть внешнему коду.

В качестве альтернативы, это не помешает просто посмотреть на real-world implementations и посмотреть, какие методы они использовали. Такие реализации часто отличаются от наиболее очевидных математических, поскольку они могут быть более эффективными для компьютеров (часто непосредственно принимая во внимание двоичные представления чисел), а также проявлять особую осторожность, чтобы избежать таких вещей, как переполнения и переполнения различных данных типы.