Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

NAN

Andrew_F_1
Beginner
552 Views

Hello,

I wrote this program:

real :: x,y,z,result

x=2

y=1

z=1

result=acos((x-y)/z)

It returns result = NAN while it should it zero and I don't know why ! any help ? 

Thanks,

Andrew.

0 Kudos
7 Replies
mecej4
Honored Contributor III
552 Views

This complete program (given below), which contains the lines that you posted, prints 0.0E+00 as the result.

Please provide details of the environment in which you obtained a NaN instead, such as OS, hardware, version of Intel Fortran used, etc.

program xacos
real :: x,y,z,result
x=2
y=1
z=1
result=acos((x-y)/z)
write(*,*)result
end

 

0 Kudos
Andrew_F_1
Beginner
552 Views

Thanks for your reply. I'm using Windows 7, Intel Xeon, Visual Studio 2005, f90 and the complete program is as follow:

Program xacos

real :: Sigma_ow, Sigma_go, Sigma_gw, Thita_go

Sigma_ow = 0.048   
Sigma_go = 0.019  
Sigma_gw = 0.067   

Thita_go = acos((Sigma_gw-Sigma_ow)/Sigma_go) 

open(unit=6 , file='GI.txt')
write(6,*) Thita_go
close(unit=6)

end program xacos

 

0 Kudos
mecej4
Honored Contributor III
552 Views

Here is the explanation: because of finite precision, the argument of acos is evaluated as 1+δ, where δ ≈ 1.2E-7, which causes the argument of acos to be outside the range of values of the cosine of a real angle.

Make sure that the argument passed to the acos function lies in the range (-1, +1), For example, you may replace the line

Thita_go = acos((Sigma_gw-Sigma_ow)/Sigma_go)

by the more robust version

Thita_go = acos(max(-1.0,min(+1.0,(Sigma_gw-Sigma_ow)/Sigma_go)))

 

0 Kudos
Andrew_F_1
Beginner
552 Views

Thanks a bunch but I can't change the equation. Do you have any idea how to fix the code ?

0 Kudos
mecej4
Honored Contributor III
552 Views

Andrew F. wrote:

Thanks a bunch but I can't change the equation. Do you have any idea how to fix the code ?

I don't quite understand your objection or what the equation is that you "can't change".

Mathematically derived expressions often rely upon the properties of real numbers (in the mathematical sense -- with as much precision as required, including infinite precision). When such expressions are implemented in a computer program on hardware that is capable of finite precision only, you have to take additional measures to avoid results such as NaN. Certain numbers that are of finite length in decimal notation, such as 0.017, do not have an exact equivalent in 32-bit real binary representation (23+1 bits for significand).

Another example similar to yours: if you add a real*4 value to itself and divide the result by 2, you may often obtain a number that differs slightly from the original number. Thus, an expression such as "x + x .eq. 2*x" may evaluate to ".false." for certain values of x.

0 Kudos
andrew_4619
Honored Contributor II
552 Views
Program xacos
implicit none
real :: Sigma_ow, Sigma_go, Sigma_gw, Thita_go, tmp, Thita_go

Sigma_ow = 0.048   
Sigma_go = 0.019  
Sigma_gw = 0.067   

tmp=(Sigma_gw-Sigma_ow)/Sigma_go
if(abs(tmp) > 1.001 ) then ! or some other meaninful tolerance value
  ! take some other action because the data is garbage and there
  ! is no valid answer
else
  if(abs(tmp) > 1.0) tmp=sign(1.0,tmp)
  Thita_go = acos(tmp) 
endif

open(unit=6 , file='GI.txt')
write(6,*) Thita_go
close(unit=6)

end program xacos

mecej4 gives a valid way, an alternative might be the one above, you need to consider what you want do to in the error case when the data is invalid. BTW I would strongly recommend always using IMPLICIT NONE forcing all vars to be declared. If you do not it will kick you in the nuts at some point.....

0 Kudos
jimdempseyatthecove
Honored Contributor III
552 Views

I might also point out the old adage:

GarbageOut = GarbageIn

Implicit in the above is you do not output non-garbage for garbage in. acos requires input argument of -1.0 to 1.0. Outside that range is garbage-in.

Jim Dempsey

0 Kudos
Reply