Reputation: 519
I am using gfortran in MinGW under Windows 7 (32bit) to compile Fortran code. Here is the minimal code contained in the file testequal.f
:
program testequal
real*8 a1, a2
a1 = 0.3d0
a2 = 0.7d0
write(*,*) 1.d0
write(*,*) a1+a2
write(*,*) a1+a2.eq.1.0
write(*,*) a1+a2.eq.1.d0
end
Compiled with
gfortran testequal.f -std=legacy
the output is:
1.0000000000000000
1.0000000000000000
F
F
But I expect the two booleans to be both T
(true). What is the problem here?
Upvotes: 8
Views: 9546
Reputation: 81
A proper comparison for reals should be agnostic of kind. This is a good way to compare:
if (abs(a1-a2) <= epsilon(a1)) print*, 'a1=a2'
Upvotes: 4
Reputation: 6158
The real issue is that 0.3 and 0.7 cannot be expressed exactly in binary.
0.3 => 0.010011001100110011.......
0.7 => 0.101100110011001100.......
When they are stored, if both are rounded up or both are rounded down, the addition of the two numbers will not get back to 1.000000000.....
This is a common error in programming simulations. Try to have step sizes that are natural to the computer:
real*8 :: dt=2.0d0**(-5)
Negative powers of two can be represented exactly in the computer. So this will actually work:
program negative_powers
real*8 :: dt = 2.0d0**(-8)
real*8 :: t = 0.0d0
do while (t .ne. 500.0d0)
print *, t
t = t + dt
end do
print *, t
end program negative_powers
Upvotes: 1
Reputation: 29391
With rare exceptions, don't compare floating point numbers for exact equality. The rules of finite-precision floating point arithmetic are not the same are the rules of real number arithmetic. Compare numbers with a tolerance, e.g.,
sum = a1 + a2
if ( abs (sum - 1.0) < 1.0D-5 ) ...
Upvotes: 11