简体   繁体   English

奇怪的战俘(x,y); 行为

[英]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. 结果是25.那没关系。 But if I write the same program like this: 但如果我写这样的程序:

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

The result is 24! 结果是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. 当x为2,3,4,6,7,8没有问题,但有5,10,11,13等结果比它应该低1。

Same thing with if(). 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,2,3,4,6,8,12,16。

std::pow() returns a floating point number. std::pow()返回一个浮点数。 If the result is for instance 24.99999999 and you cast it to int , it will be cut off to 24 . 如果结果是例如24.99999999并且你将它转换为int ,它将被切断为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. cout不会转换为int并在第一个代码示例中输出正确的结果。

'pow' returns a double value, not an int. 'pow'返回一个double值,而不是int。 The double value gets truncated when cast as an int. 当转换为int时,double值会被截断。

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

Comparing double to int is not recommended. 不建议将double与int进行比较。

http://www.cplusplus.com/reference/cmath/pow/ 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;

The pow function works with float and double , not integers. pow函数使用floatdouble ,而不是整数。 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. 话虽这么说,如果你使用double值而不是int ,你可能会看到你期望的结果。

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 . pow()函数通常在数学库中实现,可能使用目标处理器中的特殊指令,对于x86,请参见如何: x86中的pow(真实,真实) However, instructions such as fyl2x and f2xm1 aren't fast, so the whole thing could take 100 CPU cycles. 但是,诸如fyl2xf2xm1类的指令并不快,因此整个过程可能需要100个CPU周期。 For performance reasons a compiler like gcc provide "built-in" functions that provide strength reduction to perform computations faster in special cases. 出于性能原因,像gcc这样的编译器提供了“内置”函数,可以在特殊情况下提供强度降低以更快地执行计算。 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. 当幂N是一个整数(如你的情况)和小(如你的情况)那么乘N倍比调用库函数更快。

In order to detect cases where the power is an integer the math library provides overloaded functions, for example double pow(double,int) . 为了检测幂是整数的情况,数学库提供了重载函数,例如double pow(double,int) You will find that gcc converts 你会发现gcc转换

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 在内部进行2次乘法,这比库调用要快得多,并且当两个操作数都是整数时,给出了预期的精确整数结果

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

in order to get this type of strength reduction you should 为了减少这种强度,你应该这样做

  1. include < cmath > 包括<cmath>

  2. compile with optimization -O2 用优化-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 在库中调用pow函数显式std::pow()以确保你得到的版本,而不是math.h中的版本

You will then match the overloaded pow function in < cmath > which looks like this 然后,您将匹配<cmath>中的重载pow函数,如下所示

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. 请注意,此函数是使用__builtin_powi实现的,当函数为小整数时,它知道pow()的强度减少。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM