Is it the round-off error?

Hi all,

I tried the following simple example and expected showing 2.218 on the screen.
But…what I got is 2.217.
How can I do ?
Thanks in advance.

      program prog
      implicit none
      real :: i
        i = 2.2175
        write(*,'(f10.3,f10.3)')2.2175, i        
      end program prog

You are seeing the fact that 2.2175 cannot be represented exactly in binary as most every real number cannot.

You can see this by changing your program slightly to print off more digits:

program prog 

implicit none 

real :: i
i = 2.2175
write(*,'(f10.3,f10.3)')2.2175, i
write(*,'(f20.10,f20.10)')2.2175, i

end program prog

When we run this:

(259) $ pgfortran test.F90 && ./a.out
     2.217     2.217
        2.2174999714        2.2174999714

you can see that 2.2175 is actually 2.2174999714, which, by rounding rules, is rounded up to 2.217 which is what the program did.

If you change i to be 2.298500, that is stored as 2.2985000610 and is printed as 2.299, so it would seem to round “as expected”.

Matt

Hi Matt,

Thanks for your response.
It’s true that the 2.2175 is recognized as 2.2174999714…
Do we have some ways to avoid this?
Thank you very much.

Feng

Hmm. For printing I’m not sure. The compiler can only really do what the Fortran standard says for those formats.

I suppose you’d have to do some REAL comparisons and if you know your 2.2175 is actually less than actual 2.2175, add a small amount and print that. You could probably whip up a subprogram to do it.

One thought is that you could change the rounding mode to “up” instead of the default “nearest”. The caveat being “2.2171” would round up to “2.218”.

% cat test.f90
      program prog
      implicit none
      real :: i
        i = 2.2171
        write(*,'(f10.3,f10.3)',round='up')2.2175, i
      end program prog

% pgfortran test.f90 ; ./a.out
     2.218     2.218
  • Mat

I’d forgotten all about ‘round’ (Fortran 2003 right?), but yeah, I guess it does work, but pushes up a lot of extra decimals. I got bored and tried them all, and it’s pretty anticlimactic:

               Round up:      2.218     2.218
             Round down:      2.217     2.217
             Round zero:      2.217     2.217
          Round nearest:      2.217     2.217
       Round compatible:      2.217     2.217
Round processor_defined:      2.217     2.217

Just part of the fun of floating-point arithmetic.