#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;
代码可以正常运行,那么代码就可以运行。
答案 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;或类似的函数,简单地将值乘以必要的次数。这样做的好处是:
您无法使用pow
进入可能出现细微舍入错误的情况。
您的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
的结果分配给double
或float
变量来避免此错误。
所以基本上
它会转换为exp(log(x) * y)
,它会产生与x^y
完全相同的结果 - 只是近似值作为浮点值。例如,5^2
将成为24.9999996
或25.00002