首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果语句以相反的方式工作

如果语句以相反的方式工作
EN

Stack Overflow用户
提问于 2022-08-18 13:27:01
回答 2查看 143关注 0票数 3

我有一个子程序ran_init ( length ),其中一个IF语句工作不正确。

下面的代码是我的原始代码的高度简化版本:

代码语言:javascript
复制
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

此代码返回结果:

代码语言:javascript
复制
  2147483647 -2147483648 -2147483648           0
 nrerror: ran_init: arith assump 3 fails
STOP program terminated by nrerror

可以看出,值hgt + 1hgng是相等的,但是在IF语句中,这些值被解释为不平等。

为什么会发生这种事?

UPD№1一些技术细节:

  1. I使用gfortran作为编译器
  2. 命令gfortran --version返回

代码语言:javascript
复制
GNU Fortran (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609

  1. 我用标志

编译我的程序

代码语言:javascript
复制
-O2 -Wall -Wextra -fbacktrace -fcheck=all -g -o

使用一定级别的优化不影响结果。

  1. my是Ubuntu16.04LTS 64位

UPD№2

我不知道为什么,但是如果创建一个新变量,比如说,hgtp类型为INTEGER ( K4B )并替换行

代码语言:javascript
复制
hgt = hg
PRINT *, hgt, hgt + 1, hgng, hgt + 1 - hgng
IF ( hgt + 1 .NE. hgng ) CALL nrerror ( 'ran_init: arith assump 3 fails' )

带线

代码语言:javascript
复制
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。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-08-18 19:46:42

代码语言:javascript
复制
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),默认标志:

代码语言:javascript
复制
  2147483647 -2147483648 -2147483648           0

对于gfortran,默认标志:

代码语言:javascript
复制
  2147483647 -2147483648 -2147483648           0
 3    fails

gfortran有什么奇怪的吗?

票数 2
EN

Stack Overflow用户

发布于 2022-08-19 06:18:09

您正遇到整数溢出,这是Fortran中一个未定义的操作。这意味着允许Fortran处理器(编译器和运行时)使用它做它喜欢的任何事情,比如做一些或多或少的随机计算,用错误消息中止编译,用错误消息在运行时中止程序,或者发射火箭启动第三次世界大战。

这意味着如果发生整数溢出,您就不能依赖某些特定的行为。通常,编译器会尽可能快地优化代码,前提是不会发生溢出(因为这样做是没有定义的,程序员有责任确保程序不会进入这种状态)。

此外,这里有两种溢出:

  • hgt + 1是很明显的,因为hgt等于HUGE().
  • hgm - 1也是溢出。在硬件上,使用整数的两种补码表示(实际上说,现在所有硬件都在博物馆之外)并不是溢出,但是Fortran模型数是对称的,因此在Fortran标准中是溢出的,而且所有的赌注都取消了。

(以上假设您是在一个系统上运行的,默认整数与K4B具有相同的类型,这些系统现在应该是大多数系统,除非您使用了一些-fdefault-integer-8或类似的选项)

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73403900

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档