29
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
    int n,i,ele;
    n=5;
    ele=pow(n,2);
    printf("%d",ele);
    return 0;
}

输出是24

我在 Code::Blocks 中使用 GNU/GCC。

怎么了?

我知道该pow函数返回 a double,但25适合 int 类型,那么为什么此代码打印 a24而不是 a 25?如果n=4; n=6; n=3; n=2;代码有效,但使用五个则无效。

4

5 回答 5

30

这是这里可能发生的事情。您应该能够通过查看编译器的pow函数实现来确认这一点:

假设你有正确的#include,(之前所有关于这个的答案和评论都是正确的——不要认为#include文件是理所当然的),标准pow函数的原型是这样的:

double pow(double, double);

你这样打电话pow

pow(5,2);

pow函数通过算法(可能使用对数),因此使用浮点函数和值来计算功率值。

pow函数不会通过简单的“将 xa 的值乘以 n 次”,因为它还必须pow使用分数指数进行计算,并且您不能以这种方式计算分数幂。

因此,使用参数 5 和 2 的计算很可能会pow导致轻微的舍入误差。当您分配给 aint时,您截断了小数值,从而产生 24。

如果您使用整数,您不妨编写自己的“intpow”或类似函数,将值简单地乘以必要的次数。这样做的好处是:

  1. 您不会遇到使用pow.

  2. 您的intpow函数很可能比对pow.

于 2014-09-05T04:42:50.170 回答
2

你想要一个用于双打的函数的 int 结果。

你也许应该使用

ele=(int)(0.5 + pow(n,2));
/*    ^    ^              */
/* casting and rounding   */
于 2014-09-05T05:06:55.427 回答
2

浮点运算并不精确。

尽管可以精确地添加和减去小值,但该pow()函数通常通过乘对数来工作,因此即使输入都是精确的,结果也不是。分配给int总是截断,所以如果不精确度是负数,你会得到 24 而不是 25。

这个故事的寓意是对整数使用整数运算,并在<math.h>要提升或截断实际参数时对函数持怀疑态度。不幸的是,除非您添加,否则 GCC 不会发出警告-Wfloat-conversion(它不在 中-Wall -Wextra,可能是因为在很多情况下,这种转换是预期和想要的)。

对于整数幂,使用乘法(如果为负数,则除法)总是更安全、更快捷,而不是pow()将后者保留在需要的地方!不过,请注意溢出的风险。

于 2016-12-15T11:28:15.810 回答
1

当您将 pow 与变量一起使用时,其结果为double. 分配给一个int截断它。

pow因此,您可以通过将结果分配给doublefloat变量来避免此错误。

所以基本上

它转换为exp(log(x) * y)将产生与浮点值不完全相同的结果x^y- 只是作为浮点值的近似近似值。所以例如5^2将成为24.999999625.00002

于 2014-09-05T04:31:09.397 回答
0

如果你不#include <math.h>知道,那么编译器不知道pow()两者double都不是的参数的类型int——所以你得到一个未定义的结果。你得到 24,我得到 16418。

于 2014-09-05T04:19:08.497 回答