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

#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适合一个inttypes,为什么这个代码打印24而不是25 ? 如果n=4; n=6; n=3; n=2; n=4; n=6; n=3; n=2; 代码的作品,但与五不。

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

假设你有正确的#include (所有以前的答案和评论都是正确的 – 不要把#include文件理所当然),标准pow函数的原型是这样的:

double pow(double, double);

你打电话像这样:

pow(5,2);

pow函数通过algorithm(可能使用对数),从而使用浮点函数和值来计算功率值。

pow函数没有经过一个天真的“乘以x的总数n次”,因为它也必须使用分数指数来计算pow ,而且你不能用这种方式来计算分数的幂。

所以使用参数5和2计算pow可能性很小,导致略微的舍入误差。 当你分配给一个int ,你截断了小数值,从而产生24。

如果你使用整数,你也可以编写你自己的“intpow”或类似的函数,只需要将这个值乘以必要的次数即可。 这样做的好处是:

  1. 你不会进入你可能会使用pow来精细舍入错误的情况。

  2. 你的intpow函数的运行速度可能比等效的pow调用要快得多。

你想从一个函数的int结果为双打。

你应该使用

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

如果你没有#include <math.h>那么编译器不知道pow()的参数types,它们都是double而不是int – 所以你得到一个未定义的结果。 你得到24,我得到了16418。

当你使用variablespow时,其结果是double 。 分配给一个int截断它。

所以你可以通过赋值powdoublefloatvariables来避免这个错误。

所以基本上

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

浮点运算不准确。

虽然小的值可以被精确地加减,但pow()函数通常是通过乘以对数来工作的,所以即使input都是精确的,结果也不是。 指定int总是截断,所以如果不精确性是负的,你会得到24而不是25。

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

对于整数幂来说,使用乘法(如果是负数除法)而不是pow()会更安全和更快速 – 保留后者在需要的地方! 不过要注意溢出的风险。