Silverfrost Forums

Welcome to our forums

Comparing floating point numbers

19 Jan 2010 1:32 #5775

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?

program warning_179
  implicit none
  real :: a
  a = 20.0
  if (a==20.0) write(*,*) 'Test true'
end program warning_179
19 Jan 2010 1:58 #5777

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.

19 Jan 2010 2:14 #5778

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.

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
20 Jan 2010 2:19 #5784

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

21 Jan 2010 4:15 #5811

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

21 Jan 2010 5:09 #5813

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:

      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

24 Jan 2010 12:08 #5831

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.

      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

Please login to reply.