[Thread Prev][Thread Next][Index]

Re: [ferret_users] Function MOD : strange behavior



For the integer division, there is often a difference between the computer implementation and the generally accepted definition in math. See https://en.wikipedia.org/wiki/Modular_arithmetic for the definition of modulo and congruence : the result of modulo is always positive.

In computer, there is a difference between the "truncated division" (also called "symmetric") and the "floored division". Most langage implement the truncated division, when the math definition is the "floored division". And I agree that modulo and integer division should be compatible to get (m div n) * n + (m mod n) == m

In Fortran, MOD and MODULO functions have different behaviour with negative numbers !! I'm afraid Fortran misses a floored division (?)

This could be a long discussion about math, computer implementation, etc ...

But my point is far more practical : I define some geographical areas with mask from latitude and longitude values. The work would be simpler if I could use a MOD (or MODULO or whatever) function that return a number in [0,360[, and not in ]-360,360[

For instance : 

I have data with longitude in [0,360]. I want to mask some of them, and plot them for longitude -30:110. This is possible because the longitude is properly defined as modulo in the NetCDF file.

I need to define the mask as : 

LET m1 = IF lat LT 63 AND ( lon GT 330 OR (lon LT 0 AND lon GT -30) ) THEN 0 ELSE 1

this would be simpler if I could write :

LET m1 = IF lat LT 63 AND MODULO(lon,360)  LT 330 THEN 0 ELSE 1

A floored division could also be useful :-)

Olivier

Le 26 août 2020 à 17:14, Ryo Furue <furue@xxxxxxxxxx> a écrit :

Hi Olivier,

On Wed, Aug 26, 2020 at 5:45 PM Olivier Marti <olivier.marti@xxxxxxxxxxxx> wrote:

yes? LIST MOD(lon    ,360), MOD(lon-360,360), MOD(lon-720,360), MOD(lon+360,360)
[ . . . ]
            EX#1   EX#2   EX#3   EX#4
1    /  1:   36.0 -324.0 -324.0   36.0

[ . . . ] 

The result of EX#2 and EX#3 puzzles me. From what I remember from my math studies, the MOD function should return a result in the interval [0,360[. All EX#s should print the same result than EX#1 and EX#4.

Is this a bug or a feature ? If this is a feature, it should be at last documented. And another MOD function with the "correct" behaviour would be strongly appreciated ;-)

This Q&A session


explains why Ferret's MOD is the "correct" one.

(m div n) * n + (m mod n) == m
 
shall be an identity for any integers m and n.  Therefore,

(m mod n) = m - (m div n) * n
          = (-324) - ( -324 div 360) * 360
          = -324 - 0 * 360
          = -324

*Your* "correct" mod is found in the form of the MODULO function in Fortran.  I don't know whether Ferret implements it or not.

To visualize what's going on, imaging an axis with integer labels and divide it into segments with a length of 360.

The MODULO(m, 360) function you want measures the distance of m from the nearest left edge of the segment. In contrast, the MOD(m, 360) function finds a vector from the nearest edge closer to 0, to m.  The vector can be leftward (negative) or rightward (positive).

By the way, for the above identity to hold for the MODULO function, we would have to redefine

-324 div 360 = -1

This kind of makes sense.  Because MODULO is one-sided (always measures from the left edge of the interval), DIV should be one-sided, too, to be consistent.

Regards,
Ryo


— 
Olivier Marti  - LSCE Bât 714 p. 1049
MERMAID Team
Normal situation :  +33 1 69 08 77 27 
Corona lockdown  :  +33 6 45 36 43 74

Attachment: smime.p7s
Description: S/MIME cryptographic signature


[Thread Prev][Thread Next][Index]
Contact Us
Dept of Commerce / NOAA / OAR / PMEL / Ferret

Privacy Policy | Disclaimer | Accessibility Statement