当我编译以下代码时
#include <stdio.h>
#include <complex.h>
#include <math.h>
double complex testVar;
int main(void) {
testVar = 10;
double complex a = 9;
double complex b = 6;
double aDouble = 9;
double bDouble = 6;
int aInt = 9;
int bInt = 6;
printf("Result of cpow() with double complex arguments: %.15f\n", creal(cpow(a, b)));
printf("Result of cpow() with double arguments: %.15f\n", creal(cpow(aDouble, bDouble)));
printf("Result of cpow() with int arguments: %.15f\n", creal(cpow(aInt, bInt)));
printf("Result of cpow() no variables: %.15f\n", creal(cpow(9, 6)));
printf("Result of pow(): %.15f\n", pow(aDouble, bDouble));
}
使用
gcc test_cpow.c -lm -Wall
(ubuntu 上的版本 11.4.0),我运行它,得到:
Result of cpow() with double complex arguments: 531441.000000000116415
Result of cpow() with double arguments: 531441.000000000116415
Result of cpow() with int arguments: 531441.000000000116415
Result of cpow() no variables: 531441.000000000000000
Result of pow(): 531441.000000000000000
cpow()有bug吗?
如果数字是实数,我希望它的行为与 pow() 具有相同的精度,尽管它们是由
double complex
类型表示的。
注意:这个问题不是由 this 回答的,因为
pow()
比 cpow()
做得更好
这实际上与glibc有关,而不是gcc。
如果我们查看
cpow
的 glibc 代码,特别是 math/s_cpow_template.c,我们会发现以下内容:
CFLOAT
M_DECL_FUNC (__cpow) (CFLOAT x, CFLOAT c)
{
return M_SUF (__cexp) (c * M_SUF (__clog) (x));
}
所以看起来
cpow
正在使用“xy = ey ln x”等价。
如果我们对实数类型进行等效操作:
printf("Result of e^(y ln x)(): %.15f\n", exp(bDouble * log(aDouble)));
结果与复杂类型的结果相匹配:
Result of e^(y ln x)(): 531441.000000000116415
在另一端,如果我们查看 math/w_pow_template.c,我们会看到
pow
包含以下代码:
M_DECL_FUNC (__pow) (FLOAT x, FLOAT y)
{
FLOAT z = M_SUF (__ieee754_pow) (x, y);
/* checks for infinity / nan, removed for brevity */
return z;
}
这看起来是在调用一个内部函数。
所以两者的区别在于,一个使用“xy = ey ln x”来得到结果,而另一个则没有。