以下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)
应该返回(在类型转换后)2147483647
而floor(-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
。
答案 0 :(得分:1)
数学 floor(inf)和floor(-inf)应返回inf和-inf,因为用标量更改无限数仍然是无限的。
有趣的是,iFort打印
-2147483648
-2147483648
与gfortran的结果相反。
此外,您使用iFort编译的第二个测试程序打印:
-2147483648 -2147483648 -2147483648
-2147483648 -2147483648 -2147483648
这里真正的问题是floor()专门返回一个整数,并且没有非规范化整数,当然也没有特殊的位模式可以存储整数中的inf或NAN等值。没有这样的规范,它的程序员要小心。