我有一个子程序ran_init ( length ),其中一个IF语句工作不正确。
下面的代码是我的原始代码的高度简化版本:
MODULE ran_state
USE nrtype
IMPLICIT NONE
INTEGER, PARAMETER :: K4B = SELECTED_INT_KIND ( 9 )
INTEGER ( K4B ), PARAMETER :: hg = HUGE ( 1_K4B ), hgm = -hg, hgng = hgm - 1
INTEGER ( K4B ), SAVE :: lenran = 0
CONTAINS
SUBROUTINE ran_init ( length )
USE nrtype; USE nrutil, ONLY: nrerror
IMPLICIT NONE
INTEGER ( K4B ), INTENT ( IN ) :: length
INTEGER ( K4B ) :: hgt
IF ( length < lenran ) RETURN
hgt = hg
PRINT *, hgt, hgt + 1, hgng, hgt + 1 - hgng
IF ( hgt + 1 .NE. hgng ) CALL nrerror ( 'ran_init: arith assump 3 fails' )
END SUBROUTINE
END MODULE ran_state此代码返回结果:
2147483647 -2147483648 -2147483648 0
nrerror: ran_init: arith assump 3 fails
STOP program terminated by nrerror可以看出,值hgt + 1和hgng是相等的,但是在IF语句中,这些值被解释为不平等。
为什么会发生这种事?
UPD№1一些技术细节:
gfortran作为编译器gfortran --version返回GNU Fortran (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609编译我的程序
-O2 -Wall -Wextra -fbacktrace -fcheck=all -g -o使用一定级别的优化不影响结果。
UPD№2
我不知道为什么,但是如果创建一个新变量,比如说,hgtp类型为INTEGER ( K4B )并替换行
hgt = hg
PRINT *, hgt, hgt + 1, hgng, hgt + 1 - hgng
IF ( hgt + 1 .NE. hgng ) CALL nrerror ( 'ran_init: arith assump 3 fails' )带线
hgt = hg
hgtp = hgt + 1
PRINT *, hgt, hgt + 1, hgng, hgt + 1 - hgng
IF ( hgtp .NE. hgng ) CALL nrerror ( 'ran_init: arith assump 3 fails' )IF语句开始将条件hgtp .NE. hgng解释为true。
发布于 2022-08-18 19:46:42
MODULE ran_state
IMPLICIT NONE
INTEGER, PARAMETER :: K4B = SELECTED_INT_KIND ( 9 )
INTEGER ( K4B ), PARAMETER :: hg = HUGE ( 1_K4B ), hgm = -hg, hgng = hgm - 1
INTEGER ( K4B ), SAVE :: lenran = 0
CONTAINS
SUBROUTINE ran_init ( length )
INTEGER ( K4B ), INTENT ( IN ) :: length
INTEGER ( K4B ) :: hgt, temp
hgt = hg
PRINT *, hgt, hgt + 1, hgng, hgt + 1 - hgng
temp = hgt + 1
IF ( temp /= hgng ) print *, 'temp fails'
IF ( hgt + 1 /= hgng ) print *, '3 fails'
END SUBROUTINE
END MODULE ran_state
program main
use ran_state
call ran_init( 0_K4B )
end program main对于ifort (英特尔fortran),默认标志:
2147483647 -2147483648 -2147483648 0对于gfortran,默认标志:
2147483647 -2147483648 -2147483648 0
3 failsgfortran有什么奇怪的吗?
发布于 2022-08-19 06:18:09
您正遇到整数溢出,这是Fortran中一个未定义的操作。这意味着允许Fortran处理器(编译器和运行时)使用它做它喜欢的任何事情,比如做一些或多或少的随机计算,用错误消息中止编译,用错误消息在运行时中止程序,或者发射火箭启动第三次世界大战。
这意味着如果发生整数溢出,您就不能依赖某些特定的行为。通常,编译器会尽可能快地优化代码,前提是不会发生溢出(因为这样做是没有定义的,程序员有责任确保程序不会进入这种状态)。
此外,这里有两种溢出:
hgt + 1是很明显的,因为hgt等于HUGE().hgm - 1也是溢出。在硬件上,使用整数的两种补码表示(实际上说,现在所有硬件都在博物馆之外)并不是溢出,但是Fortran模型数是对称的,因此在Fortran标准中是溢出的,而且所有的赌注都取消了。(以上假设您是在一个系统上运行的,默认整数与K4B具有相同的类型,这些系统现在应该是大多数系统,除非您使用了一些-fdefault-integer-8或类似的选项)
https://stackoverflow.com/questions/73403900
复制相似问题