问题
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
include < cmath >
- compile with optimization -O2
- 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