|
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
stfark1
Joined: 02 Sep 2008 Posts: 210
|
Posted: Tue Mar 24, 2015 7:02 pm Post subject: Logical Comparisons |
|
|
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 |
|
|
dfwlms
Joined: 04 Jan 2005 Posts: 20 Location: Huntsville, Alabama
|
Posted: Tue Mar 24, 2015 7:22 pm Post subject: |
|
|
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 |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Tue Mar 24, 2015 9:07 pm Post subject: |
|
|
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 |
|
|
JohnCampbell
Joined: 16 Feb 2006 Posts: 2554 Location: Sydney
|
Posted: Wed Mar 25, 2015 2:49 am Post subject: |
|
|
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 |
|
|
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2388 Location: Yateley, Hants, UK
|
Posted: Wed Mar 25, 2015 10:04 am Post subject: |
|
|
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 |
|
|
|
|
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
|