奇怪的C程序行为

时间:2016-09-09 17:56:36

标签: c math gcc mingw assertion

我有以下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)));
}

我在Windows 8.1上运行MinGW。 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。

谢谢!

修改

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

2 个答案:

答案 0 :(得分:1)

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的半正方形逼近法。

答案 1 :(得分:1)

你有一个很好的答案(和解决方案)来自@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)));