6

While doing my homework I noticed something really strange that I just can't figure out why.

int x = 5;
cout << pow(x, 2);

The result is 25. That's fine. But if I write the same program like this:

int x = 5;
int y = pow(x, 2);
cout << y;

The result is 24!

When x is 2, 3, 4, 6, 7, 8 no problem, but with 5, 10, 11, 13 etc. result is 1 lower than it should be.

Same thing with if().

for (int x = 1; x <= 20 ; x++) {
    if (x * x == pow(x, 2)) 
    cout << x << endl;
}

It prints out numbers 1, 2, 3, 4, 6, 8, 12, 16.

David G
  • 94,763
  • 41
  • 167
  • 253
SoapyCro
  • 175
  • 2
  • 9
  • can you paste your complete code? – Techmonk Feb 05 '13 at 18:16
  • It is never a good idea to write pow(x,2), x*x is better for all purposes. A good implementation of pow, with correct rounding, would yield the result you expect (5 and 25 can be represented exactly). However, writing a correct pow is a lot of work and the result may be slow, so many implementations use some approximation that can have surprising effects. – Marc Glisse Feb 05 '13 at 18:46
  • 2
    One question per post please. Make another question for that. – David G Feb 05 '13 at 19:19
  • 1
    A lot of duplicates [Why pow(10,5) = 9,999 in C++](http://stackoverflow.com/q/9704195/995714), [Strange behaviour of the pow function](http://stackoverflow.com/q/18155883/995714), [Why am I getting unexpected output when using floor with pow?](http://stackoverflow.com/q/27479620/995714), [C's pow() function as per header file not working properly](http://stackoverflow.com/q/3509423/995714), [return value of pow() gets rounded down if assigned to an integer](http://stackoverflow.com/q/7937286/995714) – phuclv Sep 06 '15 at 05:08

4 Answers4

10

std::pow() returns a floating point number. If the result is for instance 24.99999999 and you cast it to int, it will be cut off to 24.

And that is what you do in the 2nd code example.
cout does not convert to int and outputs the correct result in the 1st code example.

juergen d
  • 201,996
  • 37
  • 293
  • 362
  • If you're going to be storing the result in an int, you might want to write a `round()` function instead of using the default behavior (truncation): http://stackoverflow.com/questions/485525/round-for-float-in-c – Robert Mason Feb 05 '13 at 18:19
  • in this case `pow()` will return the double value.? – Arpit Feb 05 '13 at 18:23
  • Thank you! I edited my post with another question so if you could check that out! – SoapyCro Feb 05 '13 at 18:31
  • @SoapyCro: Please don't add other questions to one question. This site is here to be useful for all people having the same problem in the future. You should try to see it like that when asking questions. – juergen d Feb 05 '13 at 19:32
6

'pow' returns a double value, not an int. The double value gets truncated when cast as an int.

http://www.cplusplus.com/reference/cmath/pow/

Comparing double to int is not recommended.

http://www.cplusplus.com/reference/cmath/pow/

Minor edit for your code to work :

int x = 5;
double y = pow(x,2);   // correct datatype
cout << y;
DhruvPathak
  • 42,059
  • 16
  • 116
  • 175
  • 1
    `operator<<` on `stdout` is a overloaded function, it treats the `double y` as `double`, i.e. `y` does not get truncated to `int`. – Arun Feb 05 '13 at 18:30
5

The pow function works with float and double, not integers. When you assign this to an integer, the value may be truncated, as floating point data has precision issues in its representation.

I recommend reading What Every Computer Scientist Should Know About Floating-Point Arithmetic, as this describes why you are seeing this behavior.

That being said, if you work with double values instead of int, you'll likely see the results you are expecting.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 1
    Good link, but I think it's a bit of an overkill for the OP's situation haha – salezica Feb 05 '13 at 18:17
  • 2
    @uʍopǝpısdn Well, yes and no - I think it's important to understand **why** this occurs, because that will prevent the OP from being confused later, and lead to better habits overall. – Reed Copsey Feb 05 '13 at 18:18
  • Why doesn't truncation apply here? -- liveworkspace.org/code/zbFCw$10 – David G Feb 05 '13 at 18:24
  • @David Different `pow()` implementations may err in different directions. Or it might notice that the inputs are integers, and return a precise result. – Barmar Feb 05 '13 at 18:31
  • @SurajJain Compiler is probably optimizing it away when they're constants/literals... – Reed Copsey Oct 10 '16 at 17:05
  • How is it optimizing ? I am a beginner so i do not really understand you. Can you elaborate – Suraj Jain Oct 10 '16 at 17:06
  • I found out the problem when doing this "https://stackoverflow.com/questions/33328560/float-to-integer-casting" – Suraj Jain Oct 10 '16 at 17:07
0

The pow() function is typically implemented in the math library, possibly using special instructions in the target processor, for x86 see How to: pow(real, real) in x86. However, instructions such as fyl2x and f2xm1 aren't fast, so the whole thing could take 100 CPU cycles. For performance reasons a compiler like gcc provide "built-in" functions that provide strength reduction to perform computations faster in special cases. When the power N is an integer (as in your case) and small (as in your case) then it is faster to multiply N times than to call the library function.

In order to detect cases where the power is an integer the math library provides overloaded functions, for example double pow(double,int). You will find that gcc converts

double x = std::pow(y,4);

internally into 2 multiplications, which is much faster than a library call, and gives the precise integer result you expect when both operands are integers

double tmp = y * y;
double x = tmp * tmp;

in order to get this type of strength reduction you should

  1. include < cmath >

  2. compile with optimization -O2
  3. call the pow function in the library explicitly std::pow() to make sure that's the version you get, and not one from math.h

You will then match the overloaded pow function in < cmath > which looks like this

inline double pow(double __x, int __i) { return __builtin_powi(__x, __i); }

Notice that this function is implemented with __builtin_powi which knows the strength reduction of pow() to multiplication when the power is a small integer.

Community
  • 1
  • 1
amdn
  • 11,314
  • 33
  • 45
  • @SurajJain I cannot reproduce your results. Please see http://stackoverflow.com/help/mcve. Here's a working example http://coliru.stacked-crooked.com/view?id=f3fced6502893c79 – amdn Oct 11 '16 at 10:39
  • pow() in 'C' language is implemented as a call to the standard library, where it has this signature "extern double pow( double, double );" Notice it takes floating point values and returns a floating point value. When you pass an integer, the compiler will convert to double (no loss of precision) and the library routine returns a double (with loss of precision) the result is then truncated towards zero (the largest integer smaller than or equal to the double). The standard library is doing an approximation using logarithms, so the result is something like 99.9999... and gets truncated to 99. – amdn Oct 11 '16 at 11:41
  • @SurajJain Also see http://stackoverflow.com/questions/2940367/what-is-more-efficient-using-pow-to-square-or-just-multiply-it-with-itself – amdn Oct 11 '16 at 11:50
  • Sir , Can You See This Question http://stackoverflow.com/questions/42164550/what-is-happening-here-in-pow-function/42165542 – Suraj Jain Feb 10 '17 at 20:00
  • @SurajJain, I added a comment to that question. – amdn Feb 10 '17 at 22:02