简体   繁体   中英

I've made a program in C that takes two inputs, x and n, and raises x to the power of n. 10^10 doesn't work, what happened?

I've made a program in C that takes two inputs, x and n, and raises x to the power of n. 10^10 doesn't work, what happened?

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

float isEven(int n)
{
    return n % 2 == 0;
}

float isOdd(int n)
{
    return !isEven(n);
}

float power(int x, int n)
{
    // base case
    if (n == 0)
    {
        return 1;
    }
    // recursive case: n is negative
    else if (n < 0)
    {
        return (1 / power(x, -n));
    }
    // recursive case: n is odd
    else if (isOdd(n))
    {
        return x * power(x, n-1);
    }
    // recursive case: n is positive and even
    else if (isEven(n))
    {
        int y = power(x, n/2);
        return y * y;
    }
    
    return true;
}

int displayPower(int x, int n)
{
    printf("%d to the %d is %f", x, n, power(x, n));
    return true;
}

int main(void)
{
    int x = 0;
    printf("What will be the base number?");
    scanf("%d", &x);
    
    int n = 0;
    printf("What will be the exponent?");
    scanf("%d", &n);
    
    displayPower(x, n);
}

For example, here is a pair of inputs that works:

./exponentRecursion 
What will be the base number?10
What will be the exponent?9
10 to the 9 is 1000000000.000000

But this is what I get for 10^10:

./exponentRecursion 
What will be the base number?10
What will be the exponent?10
10 to the 10 is 1410065408.000000

Why does this write such a weird number?

BTW, 10^11 returns 14100654080.000000, exactly ten times the above.

Perhaps it may be that there is some "Limit" to the data type that I am using? I am not sure.

A float only has enough precision for about 7 decimal digits. Any number with more digits than that will only be an approximations.

If you switch to double you'll get about 16 digits of precision.

When you start handling large numbers with the basic data types in C, you can run into trouble.

Integral types have a limited range of values (such as 4x10 9 for a 32-bit unsigned integer). Floating point type haver a much larger range (though not infinite) but limited precision. For example, IEEE754 double precision can give you about 16 decimal digits of precision in the range +/-10 308

To recover both of these aspects, you'll need to use a bignum library of some sort, such as MPIR .

Your variable x is an int type. The most common internal representation of that is 32 bits. That a signed binary number, so only 31 bits are available for representing a magnitude, with the usual maximum positive int value being 2^31 - 1 = 2,147,483,647. Anything larger that that will overflow, giving a smaller magnitude and possibly a negative sign.

For a greater range, you can change the type of x to long long (usually 64 bits--about 18 digits) or double (usually 64 bits, with 51 bits of precision for about 15 digits).

(Warning: Many implementations use the same representation for int and long , so using long might not be an improvement.)

If you are mixing different data types in a C program, there are several implicit casts done by the compiler. As there are strong rules how the compiler works one can exactly figure out, what happens to your program and why.

As I do not know all of this casting rules, I did the following: Estimating the maximum of precision needed for the biggest result. Then casting explicit every variable and funktion in the process to this precision, even if it is not necessary. Normally this will work like a workarount.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM