使用我的编译器和操作系统时,为什么当n = 5时pow(n,2)返回24?

时间:2014-09-05 04:08:57

标签: c math.h c-standard-library

#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函数返回double,但25符合int类型,那么为什么此代码会打印24而不是25 ?如果n=4; n=6; n=3; n=2;代码可以正常运行,那么代码就可以运行。

5 个答案:

答案 0 :(得分:25)

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

假设您拥有正确的#include&#39;(之前的所有答案和评论都是正确的 - 不要将#include文件视为理所当然),标准的原型pow函数是这样的:

double pow(double, double);

并且您正在调用pow,如下所示:

pow(5,2);

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

pow函数没有经过简单的&#34;乘以x的总和n次&#34;,因为它还必须使用小数指数计算pow,而你无法以这种方式计算分数幂。

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

如果你使用整数,你也可以写自己的&#34; intpow&#34;或类似的函数,简单地将值乘以必要的次数。这样做的好处是:

  1. 您无法使用pow进入可能出现细微舍入错误的情况。

  2. 您的intpow函数的运行速度可能比同等调用pow的速度快。

答案 1 :(得分:2)

你想要一个意味着双打的函数的int结果。

您应该使用

ele=(int)(0.5 + pow(n,2));
/*    ^    ^              */
/* casting and rounding   */

答案 2 :(得分:2)

Floating-point arithmetic is not exact.

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

这个故事的寓意是对整数使用整数运算,并且在要提升或截断实际参数时要怀疑<math.h>函数。遗憾的是GCC没有警告,除非你添加-Wfloat-conversion(它不在-Wall -Wextra,可能是因为很多情况下预期和想要这样的转换。)

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

答案 3 :(得分:1)

如果你没有#include <math.h>那么编译器不知道pow()的{​​{1}}而不是double的参数类型 - 所以你得到一个未定义的结果。你得到24,我得到16418。

答案 4 :(得分:1)

当您对变量使用pow时,其结果为double。分配给int会截断它。

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

所以基本上

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