问题
I have this function:
#include <complex.h>
complex double f(complex double x, complex double y) {
return x*y;
}
I would like to call it with x = inf + i inf
and y = i inf
and see what the result is. In particular I want to test if the result is an infinity value (as it should be) or if it is NaN + iNaN
. The reason for this is to test different C compilers.
How do you do this in C?
回答1:
I would add an intermediate check, too:
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
#include <math.h>
complex double f(complex double x, complex double y) {
return x*y;
}
int main(void){
complex double x = INFINITY + INFINITY * I;
complex double y = 0.0 + INFINITY * I;
complex double ret;
printf("x = %g + %g*I\n", creal(x), cimag(x));
printf("y = %g + %g*I\n", creal(y), cimag(y));
ret = f(x,y);
printf("f = %g + %g*I\n", creal(ret), cimag(ret));
exit(EXIT_SUCCESS);
}
Why?
Result with gcc-4.9.real (Ubuntu 4.9.4-2ubuntu1~14.04.1) 4.9.4
x = nan + inf*I
y = nan + inf*I
f = -inf + -nan*I
Result with Ubuntu clang version 3.4-1ubuntu3 (tags/RELEASE_34/final) (based on LLVM 3.4)
x = nan + inf*I
y = nan + inf*I
f = nan + nan*I
A complete and utter failure from the get go.
回答2:
I'm not 100% sure this is correct since I've never worked with complex numbers in C, but I've tried this snippet:
#include <stdio.h>
#include <math.h>
#include <complex.h>
double complex f(double complex x, double complex y) {
return x*y;
}
int main(void)
{
double complex z1 = INFINITY + INFINITY * I;
double complex z2 = INFINITY + INFINITY * I;
complex double result = f(z1, z2);
printf("%f + i%f\n", creal(result), cimag(result));
}
I used both clang 3.8 (C 11) and GCC 6.1 (C 11) and the result was:
-inf + i-nan
Based on http://en.cppreference.com/w/c/numeric/math/INFINITY.
Apparently the macro INFINITY
is not always supported and thus defined. Check the link above for more info.
回答3:
You can specify what is basically a complex literal using multiplication with the I
macro (which also has a _Complex_I
alias). A minor example creating such a value is seen below:
#include <math.h>
#include <complex.h>
int main()
{
complex c = INFINITY * I + INFINITY;
}
回答4:
The function, as written, is fine, the problem is with the way the complex numbers with special values are created and interpreted.
If you just write
double complex z1 = I * INFINITY;
double complex z2 = INFINITY + I * INFINITY;
you may discover that most of the popular compilers today do not support C99's imaginary numbers, and this expression actually multiplies (0,1) by (inf,0) and then adds (inf,0) to the result.
With gcc, I get z1 = (nan, inf), z2 = (nan, inf), f(z1,z2) = (-inf, -nan)
with clang, I get z1 = (nan, inf), z2 = (nan, inf), f(z1,z2) = (-inf, -nan)
with icc, I get z1 = (-nan, inf), z2 = (-nan, inf), f(z1, z2) = (-nan, -nan)
The only compiler that defines I as a pure imaginary number that I have access to is the C compiler from Oracle Studio
with oracle studio, I get z1 = (0, inf), z2 = (inf, inf), f(z1,z2) = (-inf, inf)
Now this is not actually supposed to be a problem because in C, there is only one Complex Infinity, and every complex number whose one component is infinite is considered to be that infinity, even if the other component is NaN. All built-in arithmetic is supposed to honor that: so in my list above, only Intel appears to have a bug here where multiplication of two complex infinities gave a complex nan.
For the lazy compilers, C11 has a macro that saves the day: CMPLX
double complex z1 = CMPLX(0, INFINITY);
double complex z2 = CMPLX(INFINITY, INFINITY);
now,
with gcc, I get z1 = (0, inf), z2 = (inf, inf), f(z1,z2) = (-inf, inf)
来源:https://stackoverflow.com/questions/42116818/how-to-pass-infinity-values-to-a-function-and-test-the-result