为什么 floor(Infinity) 给出符号相反的大整数?
Why does floor(Infinity) give large integer with opposite sign?
以下 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
returns 是一个整数。
我不明白他们的符号...从数学上讲,数轴是:
-Infinity -2147483648 0 2147483647 Infinity
--------------------------------------------------------->
但显然我的程序是相反的。 数学上来说,floor(inf)
应该return(类型转换后)2147483647
和floor(-inf)
应该return-2147483648
.
符号变化的原因是什么? gfortran 使用什么约定来产生这个奇怪的结果? Fortran 中是否有更普遍的约定?
此外,其他进行类型转换的函数 return 奇怪(至少对我而言)值:
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
return这是一个非常奇怪的结果:
-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
。
数学上 floor(inf) 和 floor(-inf) 应该 return inf 和 -inf 因为用标量改变无限数仍然是无限的。
有趣的是,iFort 打印
-2147483648
-2147483648
与 gfortran 结果相反。
此外,您使用 iFort 编译的第二个测试程序打印:
-2147483648 -2147483648 -2147483648
-2147483648 -2147483648 -2147483648
这里真正的问题是 floor() 具体 return 是一个整数,没有 非规范化 整数,当然也没有可以存储值的特殊位模式作为整数中的 inf 或 NAN。没有这样的规范,它的程序员要小心了。
以下 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
returns 是一个整数。
我不明白他们的符号...从数学上讲,数轴是:
-Infinity -2147483648 0 2147483647 Infinity
--------------------------------------------------------->
但显然我的程序是相反的。 数学上来说,floor(inf)
应该return(类型转换后)2147483647
和floor(-inf)
应该return-2147483648
.
符号变化的原因是什么? gfortran 使用什么约定来产生这个奇怪的结果? Fortran 中是否有更普遍的约定?
此外,其他进行类型转换的函数 return 奇怪(至少对我而言)值:
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
return这是一个非常奇怪的结果:
-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
。
数学上 floor(inf) 和 floor(-inf) 应该 return inf 和 -inf 因为用标量改变无限数仍然是无限的。
有趣的是,iFort 打印
-2147483648
-2147483648
与 gfortran 结果相反。
此外,您使用 iFort 编译的第二个测试程序打印:
-2147483648 -2147483648 -2147483648
-2147483648 -2147483648 -2147483648
这里真正的问题是 floor() 具体 return 是一个整数,没有 非规范化 整数,当然也没有可以存储值的特殊位模式作为整数中的 inf 或 NAN。没有这样的规范,它的程序员要小心了。