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

main() 
{

    int x, y;

    printf("Enter a number ");
    scanf("%d", &x);

    y = pow(x,15);

    printf("This is your new number %d", y);
}

When I pass x as 2, 3 or 4 it gives the correct result, but when I pass in 5 or any number higher than 5, it gives -2147483648, which is obviously incorrect.

What is the problem here? Any thoughts?

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
wujovic
  • 67
  • 1
  • 1
  • 6
  • 2
    The result is out of range. – dbush Jun 30 '21 at 14:36
  • 4
    What is the highest value representable in that datatype in your environment? Is it enough to represent the value you expect? – Yunnosch Jun 30 '21 at 14:37
  • @dbush Can we close this as typo/thinko? Or do we need an answer to get rid of this? Or a dupe? – Yunnosch Jun 30 '21 at 14:38
  • `5**15 = 30517578125 > 2147483647 = 2**31 - 1` – MikeCAT Jun 30 '21 at 14:39
  • `double y = pow(x, 15); printf("%d ^ 15 = %f\n", x, y);` – pmg Jun 30 '21 at 14:40
  • 3
    Does this answer your question? [Pow() calculates wrong?](https://stackoverflow.com/questions/8174909/pow-calculates-wrong) – Raymond Chen Jun 30 '21 at 14:40
  • 2
    I don't know why someone would downvote this question. It is well written, clear, to the point, contains example code and output, and has a clear solution that could apply to many people. Just because you know the answer, folks, doesn't mean you should downvote the question. – Gabriel Staples Jun 30 '21 at 14:42
  • The answer is `y` is an int, and can't hold the large output value, so you get signed overflow into the negative number space, which is undefined behavior. Choose a larger data type for `y`. – Gabriel Staples Jun 30 '21 at 14:44
  • 1
    Choose a larger data type for `y`, like `long long` (even better: `int64_t`). – Gabriel Staples Jun 30 '21 at 14:50
  • 1
    In my opinion, the reason that was chosen for closing this question ("This question is not reproducible or was caused by typos.") is one of the reasons Stack Overflow is considered unfriendly towards beginners, and frequently drives them away. – Gabriel Staples Jun 30 '21 at 14:52
  • 2
    @GabrielStaples Since the majority of close votes were for "Not repro", that's what the close reason is given as, and my name still gets attached to it, leading to the false impression that I voted to close as "not repro". For the record, I voted to close as duplicate. – Raymond Chen Jun 30 '21 at 22:33
  • @RaymondChen, thanks for the info. – Gabriel Staples Jun 30 '21 at 23:57
  • Since this question is in fact perfectly reproducible (run it online here: https://onlinegdb.com/faBLW62eQ), and does exactly what the OP says it does, and how he says it does it, I'm voting to re-open. – Gabriel Staples Jun 30 '21 at 23:57
  • @wujovic, note that `pow()` returns a type `double`, which uses exponential notation to represent larger numbers, at the cost of losing precision as the number grows away from zero. See the `pow()` reference here: https://en.cppreference.com/w/c/numeric/math/pow. To go even larger, use `powl()` to do the math with the `long double` type. – Gabriel Staples Jul 01 '21 at 00:01

2 Answers2

3

In your environment, the int data type is not large enough to hold the value 515. The int type on your system is likely only 32-bit, and since it is a signed type, you have only 31 bits, so the largest positive integer that it can hold is (232 - 1).

Since 515 > (232 - 1), the result that is stored in y overflows. Since pow returns double type, the behaviour of this overflowing conversion is undefined. As with all undefined behaviour, there is no guarantee about what will happen. Even running the same program twice in a row may produce different results.

dreamlax
  • 93,976
  • 29
  • 161
  • 209
  • 1
    It is common on x86-based machines to return INT_MIN (the most negative integer value) when converting an out of range float/double to int, as that is what the x86 instructions that do this conversion do. – Chris Dodd Jul 01 '21 at 00:23
0

The answer is y is an int, and can't hold the large output value, so you get signed overflow into the negative number space, which is undefined behavior and should be considered a bug you need to fix. Choose a larger data type for y, such as long long, or even better, int64_t (included with #include <stdint.h>, or double, which is the type pow() naturally returns. See here: https://en.cppreference.com/w/c/numeric/math/pow.

Note that pow() returns a type double, which uses exponential notation to represent larger numbers, at the cost of losing precision as the number grows away from zero. To go even larger, use powl() to do the math with the long double type, and then make y of type long double as well.

This is a related answer that may be considered by some to be a duplicate, since a very similar problem is happening: Pow() calculates wrong?.

Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265