Бесконечность в Фортране

каков самый безопасный способ установить переменную в + бесконечность в Fortran? На данный момент я использую:

program test
  implicit none
  print *,infinity()
contains
  real function infinity()
    implicit none
    real :: x
    x = huge(1.)
    infinity = x + x
  end function infinity
end program test

но мне интересно, есть ли лучший способ?

5 ответов


Если ваш компилятор поддерживает ISO TR 15580 IEEE арифметика, которая является частью так называемого стандарта Fortran 2003, чем вы можете использовать процедуры из модулей ieee_*.

PROGRAM main

  USE ieee_arithmetic

  IMPLICIT NONE

  REAL :: r

  IF (ieee_support_inf(r)) THEN
    r = ieee_value(r,  ieee_negative_inf)
  END IF

  PRINT *, r

END PROGRAM main

Я не уверен, работает ли решение ниже на всех компиляторах, но это хороший математический способ достижения бесконечности как-log(0).

program test
  implicit none
  print *,infinity()
contains
  real function infinity()
    implicit none
    real :: x
    x = 0
    infinity=-log(x)
  end function infinity
end program test

также хорошо работает для сложных переменных.


Я бы не стал полагаться на компилятор для поддержки стандарта IEEE и делать в значительной степени то, что вы сделали, с двумя изменениями:

  1. Я бы не добавить huge(1.)+huge(1.), Так как на некоторых компиляторах вы можете получить -huge(1.)+1 - - - и это может вызвать утечку памяти (не знаю причины, но это экспериментальный факт, так сказать).

  2. вы используете real здесь типов. Я лично предпочитаю держать все мои числа с плавающей запятой как real*8, следовательно, все константы float квалифицируются с d0, например: huge(1.d0). Это не правило, конечно, некоторые люди предпочитают использовать как realи real*8 - s.


Я не знаю о safest, но я могу предложить вам альтернативный метод. Я научился делать это так:--2-->

PROGRAM infinity
  IMPLICIT NONE
  INTEGER :: inf
  REAL :: infi
  EQUIVALENCE (inf,infi) !Stores two variable at the same address
  DATA inf/z'7f800000'/ !Hex for +Infinity
  WRITE(*,*)infi
END PROGRAM infinity

Если вы используете исключительного значения в выражениях (я не думаю, что это вообще целесообразно), вы должны обратить пристальное внимание на то, как ваш компилятор обрабатывает их, вы могли бы получить неожиданные результаты.


Это, кажется, работает для меня. Определите параметр

double precision,parameter :: inf = 1.d0/0.d0

затем используйте его в тестах if.

  real :: sng
  double precision :: dbl1,dbl2

  sng = 1.0/0.0
  dbl1 = 1.d0/0.d0
  dbl2 = -log(0.d0)

  if(sng == inf) write(*,*)"sng = inf"
  if(dbl1 == inf) write(*,*)"dbl1 = inf"
  if(dbl2 == inf) write(*,*)"dbl2 = inf"
  read(*,*)

при компиляции с помощью ifort & run я получаю

sng = inf
dbl1 = inf
dbl2 = inf