为什么C的pow()比cpow()更精确?

问题描述 投票:0回答:1

当我编译以下代码时

#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()

做得更好
c complex-numbers
1个回答
0
投票

这实际上与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”来得到结果,而另一个则没有。

© www.soinside.com 2019 - 2024. All rights reserved.