cproj功能未按预期工作

cproj功能未按预期工作,c,C,我有以下C测试程序,它使用了cproj功能: #include <stdio.h> #include <math.h> #include <complex.h> int main(void) { complex double z = cproj(INFINITY + NAN * I); printf("re=%f\nim=%f", creal(z), cimag(z)); } 但是,根据N2176 7.3.9.5(以及N

我有以下C测试程序,它使用了
cproj
功能:

#include <stdio.h>
#include <math.h>
#include <complex.h>

int main(void)
{
    complex double z = cproj(INFINITY + NAN * I);
    printf("re=%f\nim=%f", creal(z), cimag(z));
}
但是,根据N2176 7.3.9.5(以及N1570 7.3.9.5和N12567.3.9.4,我没有真正的ISO C标准,只有草案),这是不正确的行为:

7.3.9.5 cproj功能

  • cproj函数计算z在黎曼球面上的投影:z投影到z,除了所有复无穷大(甚至那些 一个无限部分和一个NaN部分)投影到正无限 在实轴上。如果z有一个无限部分,那么cproj(z)是 相当于
    无穷大+I*copysign(0.0,cimag(z))

  • 变量
    z
    有一个无限部分和一个NaN部分,但函数返回两个NaN部分,而不是实部分的无穷大。这是为什么?

    正如@EdmCoff所指出的,问题不在于
    cproj
    ,而在于变量的初始化,
    INFINITY+NAN*I
    。此示例显示:

    complex double z = INFINITY + NAN * I;
    printf("re=%f\nim=%f", creal(z), cimag(z));
    
    输出:

    re=1.#QNAN0
    im=1.#QNAN0
    
    re=1.#INF00
    im=1.#QNAN0
    
    即使未使用
    cproj
    ,变量初始化也不正确

    如果
    CMPLX
    宏可用(在任何声称实现复杂算法的C11/C17实现上,它应该是可用的,但由于某些原因,在MinGW上它不是),它应该解决以下问题:

    complex double z = CMPLX(INFINITY, NAN);
    printf("re=%f\nim=%f", creal(z), cimag(z));
    
    如果宏不可用,则初始化数字的便携式一致方法为:

    complex double z;
    memcpy(&z, (double[2]){ INFINITY, NAN }, sizeof z);
    printf("re=%f\nim=%f", creal(z), cimag(z));
    
    或者,不使用
    memcpy

    complex double z = *(complex double*)(double[2]){ INFINITY, NAN };
    printf("re=%f\nim=%f", creal(z), cimag(z));
    
    输出:

    re=1.#QNAN0
    im=1.#QNAN0
    
    re=1.#INF00
    im=1.#QNAN0
    

    正如@EdmCoff所指出的,问题不在于
    cproj
    ,而在于变量
    INFINITY+NAN*I
    的初始化。此示例显示:

    complex double z = INFINITY + NAN * I;
    printf("re=%f\nim=%f", creal(z), cimag(z));
    
    输出:

    re=1.#QNAN0
    im=1.#QNAN0
    
    re=1.#INF00
    im=1.#QNAN0
    
    即使未使用
    cproj
    ,变量初始化也不正确

    如果
    CMPLX
    宏可用(在任何声称实现复杂算法的C11/C17实现上,它应该是可用的,但由于某些原因,在MinGW上它不是),它应该解决以下问题:

    complex double z = CMPLX(INFINITY, NAN);
    printf("re=%f\nim=%f", creal(z), cimag(z));
    
    如果宏不可用,则初始化数字的便携式一致方法为:

    complex double z;
    memcpy(&z, (double[2]){ INFINITY, NAN }, sizeof z);
    printf("re=%f\nim=%f", creal(z), cimag(z));
    
    或者,不使用
    memcpy

    complex double z = *(complex double*)(double[2]){ INFINITY, NAN };
    printf("re=%f\nim=%f", creal(z), cimag(z));
    
    输出:

    re=1.#QNAN0
    im=1.#QNAN0
    
    re=1.#INF00
    im=1.#QNAN0
    

    我认为这是
    creal
    的问题,而不是
    cproj
    @EugeneSh的问题。使用
    ((double*)(&z))[0]
    也会返回NaN。不确定强制转换在技术上是否为UB,但它应该可以工作,因为复数必须是由2个浮点组成的数组。我认为问题不在于
    cproj
    ,而在于您传递的内容。我的手册页上说(关于使用
    a+b*I
    初始化复数):“某些复数不能用这种技术初始化,因为我实际上是一个复数。”既然你没有可用的
    CMPLX
    ,也许你可以创建自己的并使用它?e、 g.
    #定义我的CMPLX(x,y)((双复数){x,y})
    初始值设定项在C中无效,但我明白你的意思。成功了,我很高兴你能解决。这并不重要,但我很好奇我发布的宏有什么问题。即使使用
    -Wall
    std=c89
    编译,我也没有收到任何警告。我认为这是
    creal
    的问题,而不是
    cproj
    @EugeneSh的问题。使用
    ((double*)(&z))[0]
    也会返回NaN。不确定强制转换在技术上是否为UB,但它应该可以工作,因为复数必须是由2个浮点组成的数组。我认为问题不在于
    cproj
    ,而在于您传递的内容。我的手册页上说(关于使用
    a+b*I
    初始化复数):“某些复数不能用这种技术初始化,因为我实际上是一个复数。”既然你没有可用的
    CMPLX
    ,也许你可以创建自己的并使用它?e、 g.
    #定义我的CMPLX(x,y)((双复数){x,y})
    初始值设定项在C中无效,但我明白你的意思。成功了,我很高兴你能解决。这并不重要,但我很好奇我发布的宏有什么问题。即使使用
    -Wall
    std=c89
    编译,我也没有收到任何警告。