SoapyCro
SoapyCro

Reputation: 175

Strange pow(x, y); behaviour

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.

Upvotes: 6

Views: 5587

Answers (4)

juergen d
juergen d

Reputation: 204756

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.

Upvotes: 10

amdn
amdn

Reputation: 11582

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.

Upvotes: 0

Reed Copsey
Reed Copsey

Reputation: 564413

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.

Upvotes: 5

DhruvPathak
DhruvPathak

Reputation: 43235

'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;

Upvotes: 6

Related Questions