TINY(x) 内函数

Mar*_*ves 2 fortran fortran90

我是一名大学讲师,本学期我将使用 Fortran 90/95 作为编程语言教授数值方法课程。课程一开始就从数字的表示开始,我想谈谈 REAL(4)、REAL(8) 和 REAL(16) 可以表示的数字的限制。我打算在 OnlineGDB 上使用以下代码(这样学生就不必在计算机上安装任何东西,这在远程学习时可能会很痛苦):

Program declare_reals

implicit none 

real(kind = 4)  :: a_huge, a_tiny ! single precision ; default if kind not specified

!real(4) :: a ! Equivalent to real(kind = 4) :: a

a_huge = huge(a_huge)
print*, "Max positive for real(4) : ", a_huge
a_tiny = tiny(a_tiny)
print*, "Min positive for real(4) : ", a_tiny 
print*, 

End Program declare_reals
Run Code Online (Sandbox Code Playgroud)

通过这段代码,我得到

 Max positive for real(4) :    3.40282347E+38                                                                                                                          
 Min positive for real(4) :    1.17549435E-38
Run Code Online (Sandbox Code Playgroud)

但是,如果我写a_tiny = tiny(a_tiny)/2.0,输出就会变成

Min positive for real(4) :    5.87747175E-39
Run Code Online (Sandbox Code Playgroud)

查看 gfortran 的文档(OnlineGDB 将其用作 f95 编译器),我的印象是以下任何内容都tiny(x)可能导致下溢,并且将显示零而不是非零数字。谁能帮我理解这里发生了什么?如果tiny(x)没有产生可表示的最小正数,那么由于函数调用而显示的是什么?

kva*_*our 5

Fortran 标准对实值进行了如下规定:

\n
\n

实数x的模型集定义为

\n

根据 Fortran 的实数模型表示

\n

其中bp是超过1的整数;每个f k都是小于b的非负整数,f 1非零s为\n+1 或\xe2\x88\x921;e是介于某个整数最大值e max和某个整数最小值e min之间的整数。对于x = 0,其指数e和数字f k被定义为零。整数参数bp、\n emine max确定模型浮点数的集合。

\n
\n

满足该定义的实数值被称为型号普通浮点数。您的系统可以表示的浮点数,即机器可表示的数字是型号的超集。它们可以(但不一定必须)包含 f 1 零 \xe2\x80\x94 的值,称为正规浮点数\ xe2\x80\x94,并且用于填充零附近的下溢间隙。

\n

Fortran 函数tiny(x), huge(x), epsilon(x), spacing(x)都是针对型号定义的。

\n

的值由b e min \xe2\x88\x92 1tiny(x)给出,对于单精度浮点数(binary32 )由2 \xe2\x88\x92126给出,并且是最小模型(正常)数。当您的系统遵循 IEEE754 时,机器可表示的数字也将包含次正规数。最小的次正规正数由二进制 32给出2 \xe2\x88\x92126 \xc3\x97 2 \xe2\x88\x9223。这解释了为什么可以除以二,即从正常到次正常的过渡。tiny(x)*epsilon(x)tiny(x)

\n
\n# 最小正规数\n0 00000001 00000000000000000000000 2 = 0080 0000 16 = 2 \xe2\x88\x92126 \xe2\x89\x88 1.1754943508 \xc3\x97 10 \xe2\x88\x92 38 \n# 最小次正规数\n0 00000000 00000000000000000000001 2 = 0000 0001 16 = 2 \xe2\x88\x92126 \xc3\x97 2 \xe2 \x88\x9223 \xe2\x89\x88 1.4012984643 \xc3\x97 10 \xe2\x 88\x9245 \n
\n

注意:划分时tiny(x)*epsilon(x)二时,gfortran 返回算术下溢错误。

\n
\n

参考:取自维基百科的值:单精度浮点格式

\n