5

I realize that if you write

    Real (Kind(0.d0))::x,y
    x = sqrt(-1.d0)
    y = sqrt(-1.d0)
    if (x == y) then
       write(*,*)'yep, they are equals', x
    endif

It compiles ok using ifort. But nothing is written, the conditional is always false, did you notice that? why is this so?

vaultah
  • 44,105
  • 12
  • 114
  • 143
JoeCoolman
  • 512
  • 3
  • 8
  • 27
  • Square root of -1 is illegal. You'll have to use complex numbers for that. Also if you are getting NaN (Not a number), NaN will never be equal to NaN. Most programs will have crashed on the first NaN. – cup Jun 27 '13 at 18:16
  • You can read about this in the answer to [this question](http://stackoverflow.com/questions/1565164/what-is-the-rationale-for-all-comparisons-returning-false-for-ieee754-nan-values). NaN's aren't numbers, and comparisons to them almost always return false. (Is the NaN you get from sqrt(-1.d0) the same as the NaN you get from 0./0.? Should they be equal? Why?) – Jonathan Dursi Jun 27 '13 at 21:36
  • My question came because I needed to perform some actions when the returned value from a function is NaN i.e. `if(outcome == sqrt(-1.d0) then etc.`. Ok @Jonathan Dursi, I've read more or less the link you pass me (because is very long answer). The conclusion is to take care with those issues in Fortran. For Fortran 1.d0/0.d0 is equal to 2.d0/0.d0. I will test this in Matlab and see what it behaves. – JoeCoolman Jun 27 '13 at 22:49
  • 1
    @JoeCoolman: This is an IEEE issue, not a Fortran issue, so Matlab will likely produce the same results as the Fortran code. – Kyle Kanos Jun 28 '13 at 12:35
  • @KyleKanos - exactly. Inf *is* equal to Inf, but NaN *isn't* equal to NaN (there are exceptions for quiet NaNs) and there are very good reasons for why that is so. Those are all baked into IEE754, and just about any language or package will be the same. In Matlab you use [isnan](http://www.mathworks.com/help/matlab/ref/isnan.html) to check for NaNs (for exactly the reasons above). In modern fortran, you can [`use ieee_arithmetic`](http://fortranwiki.org/fortran/show/ieee_arithmetic) and use the intrinisic `IEEE_IS_NAN(X)` to check for NaNs. – Jonathan Dursi Jun 28 '13 at 13:51

1 Answers1

16

NaN signifies not a number, and since there are many, different, reasons a calculation could give that result, they generally do not compare as equal against themselves. If you want to do nan-testing, fortran compilers that support the f2003 standard (which is recent versions of most compilers) have ieee_is_nan in the ieee_arithmetic module:

program testnan
    use ieee_arithmetic

    real (kind=kind(0.d0)) :: x,y,z

    x = sqrt(-1.d0)
    y = sqrt(-1.d0)
    z = 1.d0

    if ( ieee_is_nan(x) ) then
       write(*,*) 'X is NaN'
    endif
    if ( ieee_is_nan(y) ) then
       write(*,*) 'Y is NaN'
    endif
    if ( ieee_is_nan(x) .and. ieee_is_nan(y) ) then
       write(*,*) 'X and Y are NaN'
    endif

    if ( ieee_is_nan(z) ) then
       write(*,*) 'Z is NaN, too'
    else
       write(*,*) 'Z is a number'
    endif

end program testnan

Compiling and running this program gives

ifort -o nan nan.f90

 X is NaN
 Y is NaN
 X and Y are NaN
 Z is a number

Unfortunately, gfortran still doesn't implement ieee_arithmetic as time of writing, so with gfortran you have to use the non-standard isnan.

Jonathan Dursi
  • 50,107
  • 9
  • 127
  • 158