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

int main()
{
    int n,i,ele;
    n=5;
    ele=pow(n,2);
    printf("%d",ele);
    return 0;
}

The output is 24.

I'm using GNU/GCC in Code::Blocks.

What is happening?

I know the pow function returns a double , but 25 fits an int type so why does this code print a 24 instead of a 25? If n=4; n=6; n=3; n=2; the code works, but with the five it doesn't.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
exsnake
  • 1,767
  • 2
  • 23
  • 44
  • Use `float ele;` (and the `%f` print format, as the *previous* code had) - what is displayed? – user2864740 Sep 05 '14 at 04:18
  • 1
    You can try taking return value of `pow` in a `float` or `double` variable, then try typecasting it to `int`. See if that also produces `24` or the correct answer `25` – 0xF1 Sep 05 '14 at 04:25
  • @Don'tYouWorryChild ya that works, but why i can't take the return value of a pow in a int?. In a test the teaching assistant told me "yes you can use a int to take the return of a pow", so... he is wrong? – exsnake Sep 05 '14 at 04:30
  • 7
    @exsnake - The `pow` function does not simply do a multiplying of 5 * 5. The final result is probably `24.9999999` or similar result. The `pow` function probably uses logarithms to compute the result, since it has to handle fractional powers also. To confirm, look at your compiler's implementation of `pow`. – PaulMcKenzie Sep 05 '14 at 04:35
  • 1
    You should clarify what OS you're using, since this is almost certainly a bug in its implementation of the math part of the standard library. I'm guessing you're using mingw with MSVCRT on Windows... – R.. GitHub STOP HELPING ICE Sep 05 '14 at 04:55
  • 1
    Can you share the output of `printf("%.25lf\n", pow(n,2));` on your implementation where `n=5`? – Mohit Jain Sep 05 '14 at 05:08
  • @MohitJain the output is 25.0000000000000000000000000 – exsnake Sep 05 '14 at 05:20
  • In that case you need to make some strange tests like: `result of double d = 25.0; int ele = d; print(ele);` and turn all optimizations off. Also try `double a = 25.0; double b = pow(n, 2);` where `n = 5;` Now compare the bit patterns of a and b in a debugger. – Mohit Jain Sep 05 '14 at 05:47
  • 3
    A good `pow(n,2)` would return exactly correct results. C does not specify how _good_ `pow()` must be. – chux - Reinstate Monica Sep 05 '14 at 14:35
  • Possible duplicate of [return value of pow() gets rounded down if assigned to an integer](https://stackoverflow.com/questions/7937286/return-value-of-pow-gets-rounded-down-if-assigned-to-an-integer) – phuclv Jun 17 '17 at 03:55
  • [Why pow(10,5) = 9,999](https://stackoverflow.com/q/9704195/995714), – phuclv Aug 31 '17 at 05:33

4 Answers4

32

Here is what may be happening here. You should be able to confirm this by looking at your compiler's implementation of the pow function:

Assuming you have the correct #include's, (all the previous answers and comments about this are correct -- don't take the #include files for granted), the prototype for the standard pow function is this:

double pow(double, double);

and you're calling pow like this:

pow(5,2);

The pow function goes through an algorithm (probably using logarithms), thus uses floating point functions and values to compute the power value.

The pow function does not go through a naive "multiply the value of x a total of n times", since it has to also compute pow using fractional exponents, and you can't compute fractional powers that way.

So more than likely, the computation of pow using the parameters 5 and 2 resulted in a slight rounding error. When you assigned to an int, you truncated the fractional value, thus yielding 24.

If you are using integers, you might as well write your own "intpow" or similar function that simply multiplies the value the requisite number of times. The benefits of this are:

  1. You won't get into the situation where you may get subtle rounding errors using pow.

  2. Your intpow function will more than likely run faster than an equivalent call to pow.

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
  • 16
    If you're going to roll your own integer-power, you should probably use [exponentiation by squaring](http://en.wikipedia.org/wiki/Exponentiation_by_squaring) rather than repeated multiplication since the latter is **O(n)** and the former is **O(log n)**. – aruisdante Oct 09 '14 at 20:43
  • 3
    @aruisdante: Beware, the notation suggests a shift from linear to logarithmic complexity, when it is actually a shift from [pseudo-linear](https://en.wikipedia.org/wiki/Pseudo-polynomial_time) to linear complexity. – Ben Voigt Nov 02 '16 at 02:54
  • 3
    @BenVoigt Technically, the previous comment should have been more specific: the naive algorithm requires O(n) arithmetic operations (multiplication or addition) where n is the exponent; squaring reduces this to O(log(n)). If we take the number of bits in n as the problem size, we might also want to count the number of bits in each product and not consider multiplication to be a constant-time operation. For the practical concerns of people doing numeric calculations, I think the Wikipedia page is overly pedantic; for complexity-theoretic concerns, its correctness is questionable. – David K Dec 10 '16 at 17:50
2

You want int result from a function meant for doubles.

You should perhaps use

ele=(int)(0.5 + pow(n,2));
/*    ^    ^              */
/* casting and rounding   */
Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
  • Better to use `ele = round(0.5 + pow(n,2));`. Although in this case `pow(n,2)` should not return results less than zero, `y = (int)(0.5 +x)` is a problem for negative `x`. – chux - Reinstate Monica Sep 05 '14 at 14:30
  • 10
    Not better! you should just use `round(pow(n,2))`. adding 0.5 before rounding effectively rounds to next integer. If `pow(n,2)` returned 25 plus epsilon, you would get 26. – chqrlie Feb 24 '15 at 01:55
2

Floating-point arithmetic is not exact.

Although small values can be added and subtracted exactly, the pow() function normally works by multiplying logarithms, so even if the inputs are both exact, the result is not. Assigning to int always truncates, so if the inexactness is negative, you'll get 24 rather than 25.

The moral of this story is to use integer operations on integers, and be suspicious of <math.h> functions when the actual arguments are to be promoted or truncated. It's unfortunate that GCC doesn't warn unless you add -Wfloat-conversion (it's not in -Wall -Wextra, probably because there are many cases where such conversion is anticipated and wanted).

For integer powers, it's always safer and faster to use multiplication (division if negative) rather than pow() - reserve the latter for where it's needed! Do be aware of the risk of overflow, though.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
1

When you use pow with variables, its result is double. Assigning to an int truncates it.

So you can avoid this error by assigning result of pow to double or float variable.

So basically

It translates to exp(log(x) * y) which will produce a result that isn't precisely the same as x^y - just a near approximation as a floating point value,. So for example 5^2 will become 24.9999996 or 25.00002

Jayesh Bhoi
  • 24,694
  • 15
  • 58
  • 73
  • i asked in a test to the the teaching assistant told about using a int instant a double in a test, and he told yes, use a int. But now i can see he was wrong. – exsnake Sep 05 '14 at 04:37
  • 1
    Your teachers assistant needs to realize that you shouldn't call functions that are meant for `double` types and assume it will use an `integer`-based implementation. – PaulMcKenzie Sep 05 '14 at 04:45