- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is actually two questions:
First is related to the behavior of the mod() intrinsic. If I compute the following using only the default flags:
mod(360., 0.1)
then the result is9.9994637E-02.According to the Intel manual and my Metcalf,Reid,and Cohen textbook,
mod(a,p) = a - int(a/p)*p.
But if I calculate this quantity:
360. - int(360./0.1)*0.1
then it gives0.0000000E+00.Is this the result of some implicit optimizations? Or is there another explanation?
The second question is similar. If I use the modulo() intrinsic instead, then I always get zero. That is:
modulo(360., 0.1)
returns0.0000000E+00. However, if I turn on the -fltconsistency flag, then it returns-5.3644180E-06.If I extend this to double precision (-r8) the numbers are different but the results are otherwise similar. But if I use the varios -fp-model flags, the result for modulo() remains zero.
I am guessing that all of these differences are the result of the inexact binary representation of 0.1. But I am not sure how to reproduce these differences, and what the best practice is for computing a modulo and determining if 'a' is a multiple of 'p'.I'd be grateful for any comments or explanations. TIA
Link Copied
1 Reply
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>what the best practice is for computing a modulo and determining if 'a' is a multiple of 'p'.
The problem that you have pointed out is that if 'p' is 0.1 that (using floating point) 'p' cannot be accurately stored in FP representation. What you are asking for is to determine if 'a' is a multiple of 'an unrepresentable number'. You have two options available:
a) determine if 'a' is approximately equal to a multiple of 'p' to within precision of 'x'
b) convert your units to precision of 'x' for all calculations then
if 'a' has fractional component or 'p' has fractional component then assume results are approximate
if 'a' and 'p' are both integral (in units of x) then *** with compiler optimizations off
temp = p / a
if((temp == int(temp)) .and. (p == (temp * a))goto isMultiple
Note, there are many subsets of a) where an exact result can be determined. However, these subsets are indistinguishable from those that are not.
For b) as an example if your precision is to 0.1 degree (or 0.01 degree) then represent your degrees as 1/10ths. IOW 3600 tenths to a circle (36000 hundredths, ...). However, bear in mind that your mantissa can saturate if you add small incriments to large values. Therfore, reduce the 'a' mod 360, (or3600, or 36000) prior to use.
Jim Dempsey
The problem that you have pointed out is that if 'p' is 0.1 that (using floating point) 'p' cannot be accurately stored in FP representation. What you are asking for is to determine if 'a' is a multiple of 'an unrepresentable number'. You have two options available:
a) determine if 'a' is approximately equal to a multiple of 'p' to within precision of 'x'
b) convert your units to precision of 'x' for all calculations then
if 'a' has fractional component or 'p' has fractional component then assume results are approximate
if 'a' and 'p' are both integral (in units of x) then *** with compiler optimizations off
temp = p / a
if((temp == int(temp)) .and. (p == (temp * a))goto isMultiple
Note, there are many subsets of a) where an exact result can be determined. However, these subsets are indistinguishable from those that are not.
For b) as an example if your precision is to 0.1 degree (or 0.01 degree) then represent your degrees as 1/10ths. IOW 3600 tenths to a circle (36000 hundredths, ...). However, bear in mind that your mantissa can saturate if you add small incriments to large values. Therfore, reduce the 'a' mod 360, (or3600, or 36000) prior to use.
Jim Dempsey
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page