- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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)))
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks a bunch but I can't change the equation. Do you have any idea how to fix the code ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.....
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page