`_Imaginary_I` 매크로 — 허수 단위 상수

_Imaginary_I 매크로 — 허수 단위 상수

복소수나 허수 타입을 다룰 때, 허수부의 음의 영(negative zero) 부호를 그대로 살려야 하는 경우가 있어요. _Complex_I로는 그 부호가 보존되지 않을 수 있다고 했죠. 이때 쓸 수 있는 정밀한 도구가 바로 _Imaginary_I예요.

출처: cppreference — _Imaginary_I

본문

_Imaginary_I 매크로는 허수 단위의 값을 가진 const float _Imaginary 타입의 값으로 확장돼요.

#define _Imaginary_I /* unspecified */   // (since C99)

C에서 순수 허수 숫자를 지원하는 것과 마찬가지로, 이 매크로는 허수 숫자가 지원될 때에만 정의돼요.

지원 여부

__STDC_IEC_559_COMPLEX__를 정의한 컴파일러라도 허수 숫자를 지원할 의무는 없어요. POSIX는 허수 숫자 지원 여부를 확인하려면 _Imaginary_I 매크로가 정의되어 있는지 검사하라고 권장해요.

  • C99~C11 이전: 허수 숫자는 __STDC_IEC_559_COMPLEX__가 정의되어 있으면 지원돼요.
  • C11부터: 마찬가지로 __STDC_IEC_559_COMPLEX__ 정의 여부로 판단해요.

Notes

이 매크로는 복소수를 실수부·허수부로부터 정밀하게 조립하는 방법을 제공해요. 예를 들어

(double complex)((double)x + _Imaginary_I * (double)y)

이런 패턴이에요. 이 패턴은 C11에서 CMPLX 매크로로 표준화됐어요. 대신 _Complex_I를 쓰면, 이 표현식이 허수 위치의 음의 영을 양의 영으로 바꿔도 허용된다는 점을 기억하세요.

예시

_Imaginary_I_Complex_I가 무한대와 만날 때 어떻게 다른지 보여주는 코드예요.

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

int main(void)
{
    double complex z1 = 0.0 + INFINITY * _Imaginary_I;
    printf("z1 = %.1f%+.1fi\n", creal(z1), cimag(z1));

    double complex z2 = 0.0 + INFINITY * _Complex_I;
    printf("z2 = %.1f%+.1fi\n", creal(z2), cimag(z2));
}

출력:

z1 = 0.0+Infi
z2 = NaN+Infi

흥미로운 차이가 보여요. _Imaginary_I 쪽은 0.0 * ∞가 실수부에서 그대로 0.0으로 유지되는 반면, _Complex_I를 쓰면 0.0 * ∞가 NaN으로 밀려나 실수부가 NaN이 돼버려요. 순수 허수 계산의 정밀성이 여기서 드러나는 거죠.

표준 참조

  • C11: 7.3.1/5 _Imaginary_I (p: 188), G.6/1 (p: 537)
  • C99: 7.3.1/3 _Imaginary_I (p: 170), G.6/1 (p: 472)

더 알아보기

  • I 매크로가 _Complex_I_Imaginary_I 중 무엇으로 확장되는지가 동작의 분기점이에요.
  • 정밀한 복소수 조립이 필요하면 CMPLX 매크로를 살펴보세요.
  • cppreference의 _Imaginary_I 원문에서 참조 절을 더 확인할 수 있어요.