奇怪的 C 程序行为

Weird C program behaviour

我有以下 C 程序:

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

int main() {
    const int opt_count = 2;

    int oc = 30;

    int c = 900;

    printf("%d %f\n", c, pow(oc, opt_count));
    assert(c == (int)(pow(oc, opt_count)));
}

我是 运行宁 MinGW Windows 8.1。 GCC 版本 4.9.3。我编译我的程序:

gcc program.c -o program.exe

当我 运行 它时,我得到这个输出:

$ program
900 900.000000
Assertion failed: c == (int)(pow(oc, opt_count)), file program.c, line 16

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

这是怎么回事?我希望断言通过,因为 900 == 30^2.

谢谢!

编辑

我没有使用任何分数或小数。我只使用整数。

pow 的实施是通过

时会发生这种情况
pow(x,y) = exp(log(x)*y)

其他库实现首先将指数减少整数次幂,从而避免了这个小的浮点错误。


更多涉及的实施包含

等步骤
pow(x,y) {
    if(y<0) return 1/pow(x, -y);

    n = (int)round(y);
    y = y-n;
    px = x; powxn = 1;
    while(n>0) {
        if(n%2==1) powxn *= px;
        n /=2; px *= px;
    }
    return powxn * exp(log(x)*y);
}

与通常的分而治之。整数幂 powxn.

的减半 n 平方方法

你从@LutzL 那里得到了一个很好的答案(和解决方案),另一个解决方案是将差异与 epsilon 进行比较,例如:0.00001,这样你就可以使用标准函数 pow包含在 math.h

#define EPSILON 0.0001
#define EQ(a, b) (fabs(a - b) < EPSILON)

assert(EQ((double)c, pow(oc, opt_count)));