我有以下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。
谢谢!
修改
我没有使用任何分数或小数。我只使用整数。
答案 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)));