Search code examples
crootpow

Why does my own power function, when used for calculating roots returns wrong result?


I implemented my own power function, which I further used for calculating a root. I wanted to compare the result returned by my function, with the one returned by the pow function, from the math.h. However, it turned out, when using my power function for calculating roots, it yields wrong answers. The square root of 15 is about 3, but my code prints 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;
}

Solution

  • Your function didn't work because its implementation uses a method that's typically used for explaining powers intuitively ("take the number 1 and multiply it exponent times by the base"). However, that method is only applicable for natural numbers. It is not the actual mathematical definition for powers with arbitrary exponents.

    If you want to have a function that works for other number spaces, you need to find a numerical method that's applicable for those those as well. Typically, those involve calculating a particular series.

    First, you need to define a function that handles these:

    1. Power for exponents that are positive integers. (This is what you have achieved.)
    2. Power for exponents that are negative integers. (You could use inversion, abs and your previous step for this.)
    3. Power for exponent equal to zero. (Luckily, this is just a constant for most cases.)

    You will also need an already-implemented ln(double x) (or you can implement it by summing a particular series that will involve your integer power function) and a factorial(int n) function (it's easy to write this, even intuitively).

    Then, you can write a function that takes any real base, and any real exponent and an integer n and do these:

    1. Calculate exponent * ln(base).
    2. Use your integer power function to calculate the n-th power of that result.
    3. Divide that result by factorial(n).

    Wrap this in a loop that sums the results of this calculation for all values of n from 0 up until the highest that can be handled validly and efficiently (the higher the maximum n, the better the approximation). That sum is the mathematical result you're looking for. Therefore, a function that takes base and exponent as parameters and runs the aforementioned loop for a series of values of n is your actual final pow function that you can expose to external code.

    Alternatively, it wouldn't hurt to just look at real-world implementations and see what methods they've used. Such implementations are often different from the most obvious mathematical ones, because they can be more efficient for computers (often directly taking into account the binary representations of the numbers involved) and also take special care to avoid things like overflows and underflows of the various data types involved.