6

在做作业时,我注意到一些非常奇怪的东西,我就是不知道为什么。

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

结果是 25。没关系。但是,如果我像这样编写相同的程序:

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

结果是24!

当 x 为 2, 3, 4, 6, 7, 8 时没问题,但对于 5, 10, 11, 13 等,结果比应有的低 1。

与 if() 相同。

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

它打印出数字 1、2、3、4、6、8、12、16。

4

4 回答 4

10

std::pow()返回一个浮点数。如果结果是例如24.99999999并且您将其转换为int,它将被截断为 24

这就是您在第二个代码示例中所做的。在第一个代码示例
cout中不转换并输出正确的结果。int

于 2013-02-05T18:16:32.090 回答
6

'pow' 返回一个双精度值,而不是一个 int。当转换为 int 时,double 值会被截断。

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

不建议将 double 与 int 进行比较。

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

对您的代码进行小幅编辑以使其正常工作:

int x = 5;
double y = pow(x,2);   // correct datatype
cout << y;
于 2013-02-05T18:16:25.477 回答
5

pow 函数适用于floatand ,而double不是整数。当您将其分配给整数时,该值可能会被截断,因为浮点数据在其表示中存在精度问题。

我建议阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic,因为这描述了您看到这种行为的原因

话虽如此,如果您使用doublevalues 而不是int,您可能会看到您期望的结果。

于 2013-02-05T18:16:57.210 回答
0

pow() 函数通常在数学库中实现,可能使用目标处理器中的特殊指令,对于 x86,请参阅 How to: pow(real, real) in x86。但是,诸如fyl2xf2xm1之类的指令并不快,因此整个过程可能需要 100 个 CPU 周期。出于性能原因,像 gcc 这样的编译器提供了“内置”函数,这些函数可以降低强度以在特殊情况下更快地执行计算。当幂N是整数(如您的情况)且较小(如您的情况)时,乘以N时间比调用库函数更快。

为了检测幂是整数的情况,数学库提供了重载函数,例如double pow(double,int). 你会发现 gcc 转换

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

在内部进行 2 次乘法运算,这比库调用快得多,并且在两个操作数都是整数时给出您期望的精确整数结果

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

为了获得这种类型的强度降低,你应该

  1. 包括 <cmath>

  2. 编译优化 -O2
  3. 显式调用库中的 pow 函数std::pow()以确保这是您获得的版本,而不是来自 math.h 的版本

然后,您将匹配 < cmath > 中的重载 pow 函数,如下所示

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

请注意,这个函数是用它来实现的,__builtin_powi当幂是一个小整数时,它知道 pow() 到乘法的强度减少。

于 2013-02-05T19:05:12.610 回答