PGI User Forum
 SearchSearch   MemberlistMemberlist     RegisterRegister   ProfileProfile    Log inLog in 

Free OpenACC Webinar

real*8 resolution not correct

 
Post new topic   Reply to topic    PGI User Forum Forum Index -> Programming and Compiling
View previous topic :: View next topic  
Author Message
bland



Joined: 27 Oct 2004
Posts: 3

PostPosted: Mon Feb 07, 2005 11:33 am    Post subject: real*8 resolution not correct Reply with quote

To start, I attempted to search for an answer to this but am not quite sure what to search for.

I have a test program:

Code:

      program realtest

      real*8 V1, V2, V3
      integer*4 i

      V1 = 1.0d0
      V2 = 0.1d0
      V3 = 0.0d0

      do i = 1,50
        V3 = V1+V2
        write(*,77) V3
 77     FORMAT(F35.30)
        V1 = V3
      enddo

      end


V1 and V2 have the proper values, with 0's filled in. However after the 6th iteration my V3 = 1.600000000000001 and the resolution continues to fluctuate for the values after that. Is there a way to specifiy the 'd0' in the V3=V2+V1 statement or am I doing something wrong like in my other posting on real*8's? Thanks for helping me understand this better.
Back to top
View user's profile
mkcolg



Joined: 30 Jun 2004
Posts: 6218
Location: The Portland Group Inc.

PostPosted: Mon Feb 07, 2005 3:33 pm    Post subject: Reply with quote

Hi bland,

What's happening here is not a Fortran specific issue. Rather, most binary real numbers can not represent exactly their decimal equivlent. Think about what the decimal equivlent of the fraction 1/3 is, .333333333.... The fraction 1/3 can not be represented exactly as a decimal so in every day life we always use an approximate value.

With the binary representation of real values, the decimal "0.1" can not be represented exactly. Instead, an approximation "0.10000000000000001" is used instead (the exact approximation will vary by system). As you add more and more values together, the error introduced by the approximation will grow.

There is a lot on the web about this issue, so doing a web search for "binary real number representation" might help.

- Mat
Back to top
View user's profile
bland



Joined: 27 Oct 2004
Posts: 3

PostPosted: Wed Feb 09, 2005 8:24 am    Post subject: Reply with quote

I understand what you wrote, but I don't understand how adding 1.0d0 + 0.1d0 can some how yeild 1.100000000000000100000000000. This crashes any loop we try to create that is dependent on the output as shown in my test case. We are trying to see if something is equal to 1.5d0 (for example) but the output never equals that exactly.

Is there a way to fill in the rest of the output values with zeros as we do with the d0 on the constants? I definitely see these resolution differences between Linux, Tru64, and VMS all of which have different "epsilons." How would you work around something like this?

Thanks for the help.
Back to top
View user's profile
mkcolg



Joined: 30 Jun 2004
Posts: 6218
Location: The Portland Group Inc.

PostPosted: Wed Feb 09, 2005 4:44 pm    Post subject: Reply with quote

Hi Bland,


Since 0.1 has an infinite binary expansion, even in double precision (ie 0.1d0) it can not be represented as an exact binary number. Adding the extra " .0000000000000001" is the closest your hardware can come to it. Other hardware might get closer, but will never be exact.

The best way to think about a REAL value is that it is an approximation and thus always wrong. It just a matter of how wrong. Granted some values can be represented, but think of these as the exception not the rule. As such, a REAL should not be used to detemine if something is equal.

One way around this is to account for the error and test if the sum is within a specified delta. Don't test for an exact match, just check if the value is within a range.

Another option if you are only using larger fractional amounts, such as .1, is to scale your value and use a INTEGER instead. An INTEGER can be used to check for equilvance. For example, if your summing U.S. dollars, instead of summing the dollars and cents, simply sum the cents. In other words, scale everything by 100 and use intergers in place of your reals. If you need more precision, simply scale by a larger amount.

Hope this helps,
Mat
Back to top
View user's profile
Display posts from previous:   
Post new topic   Reply to topic    PGI User Forum Forum Index -> Programming and Compiling All times are GMT - 7 Hours
Page 1 of 1

 
Jump to:  
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 © phpBB Group