In C, complex numbers are float or double and have same problem as canonical types:
#include <stdio.h>
#include <complex.h>
int main(void)
{
double complex a = 0 + I * 0;
double complex b = 1 + I * 1;
for (int i = 0; i < 10; i++) {
a += .1 + I * .1;
}
if (a == b) {
puts("Ok");
}
else {
printf("Fail: %f + i%f != %f + i%f\n", creal(a), cimag(a), creal(b), cimag(b));
}
return 0;
}
The result:
$ clang main.c
$ ./a.out
Fail: 1.000000 + i1.000000 != 1.000000 + i1.000000
I try this syntax:
a - b < DBL_EPSILON + I * DBL_EPSILON
But the compiler hate it:
main.c:24:15: error: invalid operands to binary expression ('_Complex double' and '_Complex double')
if (a - b < DBL_EPSILON + I * DBL_EPSILON) {
~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This last works fine but it’s a little fastidious:
fabs(creal(a) - creal(b)) < DBL_EPSILON && fabs(cimag(a) - cimag(b)) < DBL_EPSILON
Answer and Explanation: For a complex number, its absolute value gives a magnitude that can be used to compare the two numbers. If the complex number is written z = x + iy, the absolute value is given by |x+iy|=√x2+y2=r | x + i y | = x 2 + y 2 = r .
It's indeed not possible to order complex numbers since they have no ordering defined. You can compare whether two complex numbers are equal or not, but not if one is larger than the other.
If the sum of two complex number is real, and also the product of two complex number is also real, then these complex numbers are conjugate to each other. The result of the multiplication of two complex numbers and its conjugate value should result in a complex number and it should be a positive value.
Two complex numbers are equal if and only if their real parts are equal and their imaginary parts are equal. I.e., a+bi = c+di if and only if a = c, and b = d.
Comparing 2 complex floating point numbers is much like comparing 2 real floating point numbers.
Comparing for exact equivalences often is insufficient as the numbers involved contain small computational errors.
So rather than if (a == b)
code needs to be if (nearlyequal(a,b))
The usual approach is double diff = cabs(a - b)
and then comparing diff
to some small constant value like DBL_EPSILON
.
This fails when a,b
are large numbers as their difference may many orders of magnitude larger than DBL_EPSILON
, even though a,b
differ only by their least significant bit.
This fails for small numbers too as the difference between a,b
may be relatively great, but many orders of magnitude smaller than DBL_EPSILON
and so return true
when the value are relatively quite different.
Complex numbers literally add another dimensional problem to the issue as the real and imaginary components themselves may be greatly different. Thus the best answer for nearlyequal(a,b)
is highly dependent on the code's goals.
For simplicity, let us use the magnitude of the difference as compared to the average magnitude of a,b
. A control constant ULP_N
approximates the number of binary digits of least significance that a,b
are allowed to differ.
#define ULP_N 4
bool nearlyequal(complex double a, complex double b) {
double diff = cabs(a - b);
double mag = (cabs(a) + cabs(b))/2;
return diff <= (mag * DBL_EPSILON * (1ull << ULP_N));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With