Strange pow(x, y); behaviour

我们两清 提交于 2019-12-30 10:08:23

问题


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.


回答1:


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.




回答2:


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



回答3:


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.




回答4:


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.



来源:https://stackoverflow.com/questions/14714115/strange-powx-y-behaviour

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!