forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Logical Comparisons

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Plato
View previous topic :: View next topic  
Author Message
stfark1



Joined: 02 Sep 2008
Posts: 109

PostPosted: Tue Mar 24, 2015 7:02 pm    Post subject: Logical Comparisons Reply with quote

Have several situations where the FTN compiler warns about logical comparisons. Given the following statement:
ALL VARIABLES A-H, O-Z ARE DECLARED DOUBLE
PRECISION, THE VARIABLE IQUAVR IS INTEGER
IQUAVR = 0
C
IF (XMIDLH .NE. FMAP .AND.
* XCOORD .LE. XMIDLH .AND
* XMINTS .EQ. XMAXTS .AND.
* YCOORD .GE. FLT0) IQUAVR = 1

THE LOGICAL RESULT IS THAT IQUAVR = 0, THE VARIABLES ARE ASSIGNED AS FOLLOWS:
XMIDLH = 1.31750000
FMAP = .000000074
XCOORD= 1.31750000
XMINTS = 1.00000000
XMAXTS = 1.00000000
YCOORD = 1.0000000
FLT0 = 0.0000000
THE OBVIOUS SOLUTION SHOULD BE THAT IQUAVR = 1 AFTER THE COMPARISON BUT IT ACTUALLY RESULTS IN IQUAVR = 0
THE COMPILER WARNS ABOUT LOGICAL COMPARISON OF VARIABLES THAT THE RESULTS MAY BE UN-PREDICTABLE. HOWEVER, HOW DOES ONE GET AROUND THIS SITUATION TO GET THE CORRECT RESULT DESIRED. PLEASE ADVISE, SID KRAFT
Back to top
View user's profile Send private message
dfwlms



Joined: 04 Jan 2005
Posts: 18
Location: Huntsville, Alabama

PostPosted: Tue Mar 24, 2015 7:22 pm    Post subject: Reply with quote

When comparing real numbers, I always use a tolerance factor. For example:

real:: numtol =1.e-12

if(x <= y+numtol)then ...

With a statement such as this, and x =1.23456 and y =1.23456, the IF test above would produce the desired result, whereas the simpler statement,

if(x <=y) then ...

might fail because of roundoff or truncation errors in the floating point numbers.
_________________
David Williams
Retired Aerospace Engineer
Huntsville, Alabama
Back to top
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 1652
Location: Yateley, Hants, UK

PostPosted: Tue Mar 24, 2015 9:07 pm    Post subject: Reply with quote

Sid,

If the numbers are input values, then the test should work, but it only takes one of them to be the result of a computation, and 'Kaboom'.

If you print out the logical result of each comparison, the 1 and 4 are definitely T but one of 2 or 3 is F.

Probably best to do a test for plus or minus, i.e.

IF (ABS(X-Y) .LE. NUMTOL) etc



Eddie
Back to top
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 1774
Location: Sydney

PostPosted: Wed Mar 25, 2015 2:49 am    Post subject: Reply with quote

Sid,

If the number you are using is not exact in binary representation, then you will have problems, as round-off will change the result, as in the following example:

Code:
     real*4    r1
     real*8    d1, d2, numtol
     integer*4 i

     do i = 1,2
!
     if (i==2) then
     r1 = 1.3175
     d1 = 1.3175d0
     d2 = 1.3175
     else
     r1 = 1.5
     d1 = 1.5d0
     d2 = 1.5
     end if
     write (*,*) 'Using d2=',d2
!
     if ( d1 == d2 ) write (*,*) 'd1 and d2 are the same'
     if ( d1 /= d2 ) write (*,*) 'd1 and d2 are different'
     write (*,*) d1-d2
!
     d2 = r1
     if ( d1 == d2 ) write (*,*) 'd1 and d2 are the same'
     if ( d1 /= d2 ) write (*,*) 'd1 and d2 are different'
     write (*,*) d1-d2
!
     d2 = d1
     if ( d1 == d2 ) write (*,*) 'd1 and d2 are the same'
     if ( d1 /= d2 ) write (*,*) 'd1 and d2 are different'
     write (*,*) d1-d2
     end do
!
     write (*,*) 'Estimation of accuracy of d1'
     numtol = abs (d1) * epsilon (d1)                         ! works if d1 /= 0

     write (*,*) 'number of digits in r1 =', precision (r1)
     write (*,*) 'epsilon for real*4     =', epsilon (r1)
     write (*,*) 'tiny    for real*4     =', tiny (r1)
     write (*,*) 'number of digits in d1 =', precision (d1)
     write (*,*) 'epsilon for real*8     =', epsilon (d1)
     write (*,*) 'tiny    for real*8     =', tiny (d1)
!
     write (*,*) 'accuracy of d1         =', numtol
     write (*,*) ' useful NUMTOL test    =', 2*numtol

end


However if you try r1 = 1.5 ; d1 = 1.5d0 ; d2 = 1.5 you will get a different result.
The correct way is how Eddie suggests, although it is more to code and you need to know what precision to apply to (real*8) NUMTOL.
Note: NUMTOL varies with the value of d1 (or d2 or the expected range of values for d1 or d2)
if d1 is zero, then you need a different approach for NUMTOL. Tiny(d1) is the smallest number near (not) zero, so you can see for small values of d1 you need an even smaller value for NUMTOL.

Effectively you need to say; How close to d1 is the same value ?

There is another case, where you initially give d2 the value of d1, then at the end of your routine you ask if d2 has changed. In this case if ( d1/= d2) will give the answer you want (and the compiler warnings)

John
Back to top
View user's profile Send private message
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 1652
Location: Yateley, Hants, UK

PostPosted: Wed Mar 25, 2015 10:04 am    Post subject: Reply with quote

John,

Perfect answer. My tolerances are often a lot more physical, e.g. for a distance in km or m, to within 1mm or 5mm!

Regards

Eddie
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Plato All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group