如何将无穷大值传递给函数并测试结果
How to pass infinity values to a function and test the result
我有这个功能:
#include <complex.h>
complex double f(complex double x, complex double y) {
return x*y;
}
我想用 x = inf + i inf
和 y = i inf
调用它,看看结果是什么。特别是我想测试结果是无穷大值(应该是)还是 NaN + iNaN
。这样做的原因是为了测试不同的C编译器。
How do you do this in C?
我不是 100% 确定这是正确的,因为我从来没有在 C 中使用过复数,但我试过这个片段:
#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));
}
我同时使用了 clang 3.8 (C 11) 和 GCC 6.1 (C 11),结果是:
-inf + i-nan
基于http://en.cppreference.com/w/c/numeric/math/INFINITY.
显然宏 INFINITY
并不总是被支持和定义。查看上面的 link 了解更多信息。
您可以使用与 I
宏(它也有一个 _Complex_I
别名)的乘法来指定基本上是一个复杂的文字。下面是创建此类值的一个小示例:
#include <math.h>
#include <complex.h>
int main()
{
complex c = INFINITY * I + INFINITY;
}
我也会添加中间检查:
#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);
}
为什么?
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
结果 Ubuntu clang 版本 3.4-1ubuntu3 (tags/RELEASE_34/final)(基于 LLVM 3.4)
x = nan + inf*I
y = nan + inf*I
f = nan + nan*I
从一开始就彻底失败。
所写的函数很好,问题在于创建和解释具有特殊值的复数的方式。
如果你只写
double complex z1 = I * INFINITY;
double complex z2 = INFINITY + I * INFINITY;
你可能会发现现在大多数流行的编译器都不支持C99的imaginary numbers,而这个表达式实际上是将(0,1)乘以(inf,0)然后加上(inf,0)结果。
使用 gcc,我得到 z1 = (nan, inf), z2 = (nan, inf), f(z1,z2) = (-inf, -nan)
用 clang,我得到 z1 = (nan, inf), z2 = (nan, inf), f(z1,z2) = (-inf, -nan)
使用 icc,我得到 z1 = (-nan, inf), z2 = (-nan, inf), f(z1, z2) = (-nan, -nan)
唯一将 I 定义为我有权访问的纯虚数的编译器是来自 Oracle Studio 的 C 编译器
使用 oracle studio,我得到 z1 = (0, inf), z2 = (inf, inf), f(z1,z2) = (-inf, inf)
现在这实际上不应该是一个问题,因为在 C 中,只有一个复数无穷大,每个一个分量为无穷大的复数都被认为是那个无穷大,即使另一个分量是 NaN 也是如此。所有 built-in 算法都是 supposed to honor that:所以在我上面的列表中,只有英特尔似乎有一个错误,其中两个复数无穷大的乘法给出了一个复数 nan。
对于懒惰的编译器,C11 有一个可以挽救一天的宏:CMPLX
double complex z1 = CMPLX(0, INFINITY);
double complex z2 = CMPLX(INFINITY, INFINITY);
现在,
使用 gcc,我得到 z1 = (0, inf), z2 = (inf, inf), f(z1,z2) = (-inf, inf)
我有这个功能:
#include <complex.h>
complex double f(complex double x, complex double y) {
return x*y;
}
我想用 x = inf + i inf
和 y = i inf
调用它,看看结果是什么。特别是我想测试结果是无穷大值(应该是)还是 NaN + iNaN
。这样做的原因是为了测试不同的C编译器。
How do you do this in C?
我不是 100% 确定这是正确的,因为我从来没有在 C 中使用过复数,但我试过这个片段:
#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));
}
我同时使用了 clang 3.8 (C 11) 和 GCC 6.1 (C 11),结果是:
-inf + i-nan
基于http://en.cppreference.com/w/c/numeric/math/INFINITY.
显然宏 INFINITY
并不总是被支持和定义。查看上面的 link 了解更多信息。
您可以使用与 I
宏(它也有一个 _Complex_I
别名)的乘法来指定基本上是一个复杂的文字。下面是创建此类值的一个小示例:
#include <math.h>
#include <complex.h>
int main()
{
complex c = INFINITY * I + INFINITY;
}
我也会添加中间检查:
#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);
}
为什么?
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
结果 Ubuntu clang 版本 3.4-1ubuntu3 (tags/RELEASE_34/final)(基于 LLVM 3.4)
x = nan + inf*I
y = nan + inf*I
f = nan + nan*I
从一开始就彻底失败。
所写的函数很好,问题在于创建和解释具有特殊值的复数的方式。
如果你只写
double complex z1 = I * INFINITY;
double complex z2 = INFINITY + I * INFINITY;
你可能会发现现在大多数流行的编译器都不支持C99的imaginary numbers,而这个表达式实际上是将(0,1)乘以(inf,0)然后加上(inf,0)结果。
使用 gcc,我得到 z1 = (nan, inf), z2 = (nan, inf), f(z1,z2) = (-inf, -nan)
用 clang,我得到 z1 = (nan, inf), z2 = (nan, inf), f(z1,z2) = (-inf, -nan)
使用 icc,我得到 z1 = (-nan, inf), z2 = (-nan, inf), f(z1, z2) = (-nan, -nan)
唯一将 I 定义为我有权访问的纯虚数的编译器是来自 Oracle Studio 的 C 编译器
使用 oracle studio,我得到 z1 = (0, inf), z2 = (inf, inf), f(z1,z2) = (-inf, inf)
现在这实际上不应该是一个问题,因为在 C 中,只有一个复数无穷大,每个一个分量为无穷大的复数都被认为是那个无穷大,即使另一个分量是 NaN 也是如此。所有 built-in 算法都是 supposed to honor that:所以在我上面的列表中,只有英特尔似乎有一个错误,其中两个复数无穷大的乘法给出了一个复数 nan。
对于懒惰的编译器,C11 有一个可以挽救一天的宏:CMPLX
double complex z1 = CMPLX(0, INFINITY);
double complex z2 = CMPLX(INFINITY, INFINITY);
现在,
使用 gcc,我得到 z1 = (0, inf), z2 = (inf, inf), f(z1,z2) = (-inf, inf)