为什么floor(无穷大)给出带有相反符号的大整数?



以下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 - %dn",iflr,irnd,icei);
iflr = floor(-inf);
irnd = round(-inf);
icei = ceil(-inf);
printf("%d - %d - %dn",iflr,irnd,icei);
}

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

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

有趣的是,iFort 打印

-2147483648
-2147483648

与Gfortran的结果相反。

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

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

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

最新更新