View previous topic :: View next topic |
Author |
Message |
jjgermis
Joined: 21 Jun 2006 Posts: 404 Location: N�rnberg, Germany
|
Posted: Tue Jan 19, 2010 2:32 pm Post subject: Comparing floating point numbers |
|
|
Quote: | warning 179 - Comparing floating point quantities for equality may give misleading results |
The warning as given here is produced when one have floating point variables in an if statement for example. This is only a warning and the code produces the correct result. Just for interest: Is the someway to avoid this in general, i.e. is there some special way to handle the comparison of floating point numbers?
Code: | program warning_179
implicit none
real :: a
a = 20.0
if (a==20.0) write(*,*) 'Test true'
end program warning_179 |
|
|
Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8210 Location: Salford, UK
|
Posted: Tue Jan 19, 2010 2:58 pm Post subject: |
|
|
The best way is to test for abs(a - 20.0) less than something small.
You will need to have some idea about the possible round off error in your calculation.
The bad way is to set the compiler to ignore this particular warning. |
|
Back to top |
|
 |
jjgermis
Joined: 21 Jun 2006 Posts: 404 Location: N�rnberg, Germany
|
Posted: Tue Jan 19, 2010 3:14 pm Post subject: |
|
|
I tried it with tiny. In this way there is no warning. However, as you mentioned one should have some idea of the round off error. I also agree that switching off the warnings is not a good idea.
Code: | program warning_179
implicit none
!Epsilon
! 1.1920929E-07
!Tiny
! 1.1754944E-38
real :: a
real,parameter :: tiny = 1.1754944E-38
a = 20.0
if (abs(a-20.0)<tiny) write(*,*) 'Test true'
end program warning_179
|
|
|
Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2615 Location: Sydney
|
Posted: Wed Jan 20, 2010 3:19 am Post subject: |
|
|
You should not limit your view of tiny to real*4 round off, but also concider the accuracy that could be tolerated for the calculation of "a".
Other possible values of tiny could be 0.1 or even 1.0.
Any value of tiny < 1.e-7 would not be sensible.
John |
|
Back to top |
|
 |
KL
Joined: 16 Nov 2009 Posts: 155
|
Posted: Thu Jan 21, 2010 5:15 pm Post subject: |
|
|
How is it if you write
if (a .eq. 0.) .... ?
It happens often that a variable is set to zero, which is exact and has no roundoff error (am I right?), so in this specific case there is no need for a warning.
Klaus |
|
Back to top |
|
 |
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2402 Location: Yateley, Hants, UK
|
Posted: Thu Jan 21, 2010 6:09 pm Post subject: |
|
|
Paul is right that switching off warnings isn't in general a good idea, but this one irritates me (a lot) because of a programming habit that I have, which is to (almost) always check that the denominator of an expresssion isn't zero before I evaluate it. Hence, I will have code such as:
Code: | IF (X .EQ. 0.0D0) THEN
. ! provide a really helpful diagnostic
ELSE
. ! go on to divide by X
ENDIF |
In this case the zero value for X is quite possibly an input value (if you input 0, you get 0 exactly), and good though the FTN95 diagnostics are, they can be bettered with chapter and verse of where the error occurred, and what it was - if you try. Checking against a small value of difference isn't what I want - I want to see (in the case above) if some idiot (usually me) has entered 0 when a non-zero number was wanted. Then, I don't want to be "ticked off" by the compiler.
To ignore a warning, use -ignore with its number on the command line, in this case 179. When you think the code works, try compiling it without the -ignore option, and check that the cases it ignored were ones you wanted ignored!
Eddie |
|
Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2615 Location: Sydney
|
Posted: Sun Jan 24, 2010 1:08 pm Post subject: |
|
|
To try and address this problem, I wrote the following logical functions, which can be applied by reformating the if statements.
By finding an estimate of what is a reaonable accuracy to allow, these have worked for me, mainly when reading data from a text file. For others, different accuracy tests may be required.
Code: | LOGICAL FUNCTION EQUAL_VALUE (VARIABLE, VALUE)
!
REAL*8 VARIABLE, VALUE, accuracy, error
!
if ( variable == value) then
equal_value = .true.
else
accuracy = max (abs(variable), abs(value), 1.d-6) * 1.d-8 ! 1.e-14 limit
error = abs (variable-value)
equal_value = error < accuracy
end if
RETURN
END
LOGICAL FUNCTION EQUAL_ZERO (VARIABLE)
!
REAL*8 VARIABLE
REAL*8, parameter :: ZERO = 0
REAL*8, parameter :: SMALL = 1.d-12
!
if ( variable == zero) then
equal_zero = .true.
else
equal_zero = abs(VARIABLE) < SMALL
end if
RETURN
END
LOGICAL FUNCTION NON_ZERO (VARIABLE)
!
REAL*8 VARIABLE
REAL*8, parameter :: ZERO = 0
REAL*8, parameter :: SMALL = 1.d-12
!
if ( variable == zero) then
non_zero = .false.
else
non_zero = abs(VARIABLE) > SMALL
end if
RETURN
END
|
They still give the 179 warning, but is is limited to a simgle warning in the utility library.
John |
|
Back to top |
|
 |
|