How to pass infinity values to a function and test the result

给你一囗甜甜゛ 提交于 2021-02-08 08:16:19

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!