为什么floor(Infinity)给出具有相反符号的大整数?

时间:2018-03-16 11:27:26

标签: fortran gfortran

以下Fortran计划:

program test
double precision :: inf, one, zero
one = 1.d0
zero = 0.d0
inf = one/zero
write(6,*) floor( inf)
write(6,*) floor(-inf)
end program test
gfortran test.f95编译的

打印出这个:

-2147483648
 2147483647

我理解为什么这些值,它们是4字节整数的最大值(或最小值),这是gfortran中的默认值,floor返回一个整数。

我没有得到的是他们的标志......数学上,数字线将是:

-Infinity    -2147483648    0    2147483647    Infinity
--------------------------------------------------------->

但显然我的计划却反过来看待它。 以数学方式发言,floor(inf)应该返回(在类型转换后)2147483647floor(-inf)应该返回-2147483648

导致标志变化的原因是什么? gfortran使用什么约定来产生这个奇怪的结果?在Fortran中是否有更普遍的约定?

此外,进行类型转换的其他函数返回奇怪的(至少对我来说)值:

write(6,*) floor( inf), nint( inf), ceiling( inf)
write(6,*) floor(-inf), nint(-inf), ceiling(-inf)

打印:

-2147483648    0   -2147483647
 2147483647    0   -2147483648

更新

在agentp的评论之后,我发现这不会发生在无限性上。任何大数字(大于2^32)都会得到相同的结果。

为了让事情更奇怪,这个程序:

program test
real :: big
big = 2.d0**32-1000
print*, big
write(6,*) floor( big), nint( big), ceiling( big)
write(6,*) floor(-big), nint(-big), ceiling(-big)
end program test

返回这个非常奇怪的结果:

-2147483648       -1024 -2147483647
 2147483647        1024 -2147483648

出于好奇,我检查了这个C程序:

#include <stdio.h>
#include <math.h>
int main()
{
   float one = 1;
   float zero = 0;
   float inf = one/zero;
   int iflr = floor(inf);
   int irnd = round(inf);
   int icei = ceil(inf);
   printf("%d - %d - %d\n",iflr,irnd,icei);
   iflr = floor(-inf);
   irnd = round(-inf);
   icei = ceil(-inf);
   printf("%d - %d - %d\n",iflr,irnd,icei);
}

使用gcc test.c -lm编译,并为所有情况打印-2147483648

1 个答案:

答案 0 :(得分:1)

数学 floor(inf)和floor(-inf)应返回inf和-inf,因为用标量更改无限数仍然是无限的。

有趣的是,iFort打印

 -2147483648
 -2147483648

与gfortran的结果相反。

此外,您使用iFort编译的第二个测试程序打印:

-2147483648 -2147483648 -2147483648
-2147483648 -2147483648 -2147483648

这里真正的问题是floor()专门返回一个整数,并且没有非规范化整数,当然也没有特殊的位模式可以存储整数中的inf或NAN等值。没有这样的规范,它的程序员要小心。