如何在 C 中分配复数变量的实部和虚部
How to assign real and imaginary parts of complex variables in C
使用C99标准的复数类型,如何分别给一个变量的实部和虚部赋值?我发现 GNU 扩展 __real__ 和 __imag__ 将执行此操作,如以下示例程序所示。但这不是便携式或标准的。如何便携地做到这一点?
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
int
main()
{
complex double z;
__real__ z = 3.0;
__imag__ z = 2.0;
fprintf(stderr, "z = %f + i %f\n", creal(z), cimag(z));
return 0;
}
How can one do this portably?
只是...补充:
z = 3.0;
z += I * 2.0;
你可以先将虚部归零,如果你想:
z = creal(z) + I * 2.0;
how does one assign the real and imaginary parts of a variable
individually?
// assign real
z = new_value + I * cimag(z);
// assign imaginary
z = creal(z) + I * new_value;
人们可能更喜欢 _Imaginary_I
或 CMPLXF
宏而不是 I
。
我找到了另一种可能的解决方案。下面的代码假定复数 double 与 double[2] 位等效(我认为这是正确的,但希望得到验证!)。我认为下面的解决方案可能更有效,因为它不涉及每个分配的额外加法操作(就像 KamilCuk 的解决方案一样)。
如果有人可以验证这是否适用于所有平台,我将不胜感激。
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
#define SET_REAL(z, x) ( *((double *) &(z)) = (x) )
#define SET_IMAG(z, x) ( *(((double *) &(z)) + 1) = (x) )
int
main()
{
complex double z;
SET_REAL(z, 3.0);
SET_IMAG(z, 2.0);
fprintf(stderr, "z = %f + i %f\n", creal(z), cimag(z));
return 0;
}
C 2018 6.2.5 13 表示我们可以将复数视为包含两个元素的数组:
Each complex type has the same representation and alignment requirements as an array type containing exactly two elements of the corresponding real type; the first element is equal to the real part, and the second element to the imaginary part, of the complex number.
这是粗略的措辞,与 6.5 7 中明确规定的别名规则不一致,但该标准并不完善,关于整数和指针的脚注 41 和 49 建议此类关于表示和对齐的陈述应该允许尽管有 6.5 中的规则,但仍将对象的一种视图用于另一种视图 7. 如果是这样,我们可以定义宏:
#define Re(x) (_Generic((x), \
complex float : ((float *) &(x)), \
complex double : ((double *) &(x)), \
complex long double : ((long double *) &(x)))[0])
#define Im(x) (_Generic((x), \
complex float : ((float *) &(x)), \
complex double : ((double *) &(x)), \
complex long double : ((long double *) &(x)))[1])
之后 Re(x)
和 Im(x)
,当给定一个复杂的对象时,产生实部或虚部的左值。所以我们可以分配它们:
Re(x) = 3;
Im(x) = 4;
使用C99标准的复数类型,如何分别给一个变量的实部和虚部赋值?我发现 GNU 扩展 __real__ 和 __imag__ 将执行此操作,如以下示例程序所示。但这不是便携式或标准的。如何便携地做到这一点?
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
int
main()
{
complex double z;
__real__ z = 3.0;
__imag__ z = 2.0;
fprintf(stderr, "z = %f + i %f\n", creal(z), cimag(z));
return 0;
}
How can one do this portably?
只是...补充:
z = 3.0;
z += I * 2.0;
你可以先将虚部归零,如果你想:
z = creal(z) + I * 2.0;
how does one assign the real and imaginary parts of a variable individually?
// assign real
z = new_value + I * cimag(z);
// assign imaginary
z = creal(z) + I * new_value;
人们可能更喜欢 _Imaginary_I
或 CMPLXF
宏而不是 I
。
我找到了另一种可能的解决方案。下面的代码假定复数 double 与 double[2] 位等效(我认为这是正确的,但希望得到验证!)。我认为下面的解决方案可能更有效,因为它不涉及每个分配的额外加法操作(就像 KamilCuk 的解决方案一样)。
如果有人可以验证这是否适用于所有平台,我将不胜感激。
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
#define SET_REAL(z, x) ( *((double *) &(z)) = (x) )
#define SET_IMAG(z, x) ( *(((double *) &(z)) + 1) = (x) )
int
main()
{
complex double z;
SET_REAL(z, 3.0);
SET_IMAG(z, 2.0);
fprintf(stderr, "z = %f + i %f\n", creal(z), cimag(z));
return 0;
}
C 2018 6.2.5 13 表示我们可以将复数视为包含两个元素的数组:
Each complex type has the same representation and alignment requirements as an array type containing exactly two elements of the corresponding real type; the first element is equal to the real part, and the second element to the imaginary part, of the complex number.
这是粗略的措辞,与 6.5 7 中明确规定的别名规则不一致,但该标准并不完善,关于整数和指针的脚注 41 和 49 建议此类关于表示和对齐的陈述应该允许尽管有 6.5 中的规则,但仍将对象的一种视图用于另一种视图 7. 如果是这样,我们可以定义宏:
#define Re(x) (_Generic((x), \
complex float : ((float *) &(x)), \
complex double : ((double *) &(x)), \
complex long double : ((long double *) &(x)))[0])
#define Im(x) (_Generic((x), \
complex float : ((float *) &(x)), \
complex double : ((double *) &(x)), \
complex long double : ((long double *) &(x)))[1])
之后 Re(x)
和 Im(x)
,当给定一个复杂的对象时,产生实部或虚部的左值。所以我们可以分配它们:
Re(x) = 3;
Im(x) = 4;