Creating Repeated Sequences With The Modulus (MOD) Operator

Posted August 10, 2011 at 9:49 AM by Ben Nadel

Tags: ColdFusion

This almost doesn't warrant its own post; but, it seems to be one of those small factoids that I can't keep in my head without writing it down. And so, a quick post to demonstrate creating repeated sequences with the modulus operator (MOD or %). To be fair, the modulus operator already creates repeated sequences; but, those sequences end with a zero. This is perfect for when you only care about one number in a particular sequence; but, when you want to deal with a sequence as a set of numbers, typically, you want your sequence to start at 1 and proceed to N.

In order to end your sequence on "N", you have to add some math to your modulus calculation. But, before we look at that, let's take a look at a simple modulus loop:

  • <!---
  • Loop to 15 using a modulus of 3 to get a result
  • at each index.
  • --->
  • <cfloop
  • index="i"
  • from="1"
  • to="15"
  • step="1">
  •  
  • #i# % 3 = #(i % 3)#<br />
  •  
  • </cfloop>

Here, we are looping from 1 to 15 and outputting the mod-3 for each index. When we run this code, we get the following output:

1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2
6 % 3 = 0
7 % 3 = 1
8 % 3 = 2
9 % 3 = 0
10 % 3 = 1
11 % 3 = 2
12 % 3 = 0
13 % 3 = 1
14 % 3 = 2
15 % 3 = 0

As you can see, this creates the repeated sequence, {1,2,0}. Like I said, standard modulus sequences end with zero. This is great if you want to determine which index you are at (1 == first, 0 == last); but, if you wanted to get the index within the repeated sequence, your logic gets a bit more tricky.

To create a repeated sequence that ends in N rather than zero, we have to add some more math to the mix:

  • <!---
  • Now, loop to 15 using a modulus of 3. However, this time,
  • rather than repeating 1,2,0, we want to repeat 1,2,3. To do
  • this, we have to use a slightly different formula:
  •  
  • ((n - 1) % 3) + 1
  • --->
  • <cfloop
  • index="i"
  • from="1"
  • to="15"
  • step="1">
  •  
  • ((#i# - 1) % 3) + 1 = #(((i - 1) % 3) + 1)#<br />
  •  
  • </cfloop>

This time, we are subtracting one from the index and then adding one to the result. When we run this code, we get the following output:

((1 - 1) % 3) + 1 = 1
((2 - 1) % 3) + 1 = 2
((3 - 1) % 3) + 1 = 3
((4 - 1) % 3) + 1 = 1
((5 - 1) % 3) + 1 = 2
((6 - 1) % 3) + 1 = 3
((7 - 1) % 3) + 1 = 1
((8 - 1) % 3) + 1 = 2
((9 - 1) % 3) + 1 = 3
((10 - 1) % 3) + 1 = 1
((11 - 1) % 3) + 1 = 2
((12 - 1) % 3) + 1 = 3
((13 - 1) % 3) + 1 = 1
((14 - 1) % 3) + 1 = 2
((15 - 1) % 3) + 1 = 3

As you can see, this time, we created the repeated sequence, {1,2,3}. With the extra math, we were able to end on N (3 in our case) rather than zero.

And, of course, we could abstract this concept out into its own function:

  • <cffunction
  • name="modSequence"
  • access="public"
  • returntype="numeric"
  • output="false"
  • hint="I return the modulus result of the given value into the given sequence such that the resultant sequence goes from 1 to N (rather than zero).">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="index"
  • type="numeric"
  • required="true"
  • hint="I am the index that we will fit into the given sequence."
  • />
  •  
  • <cfargument
  • name="sequence"
  • type="numeric"
  • required="true"
  • hint="I am sequence (max value) into which we will be fitting the given index."
  • />
  •  
  • <cfreturn (((arguments.index - 1) % arguments.sequence) + 1) />
  • </cffunction>
  •  
  •  
  • <!--- loop to 15, repeating 1,2,3. --->
  • <cfloop
  • index="i"
  • from="1"
  • to="15"
  • step="1">
  •  
  • modSequence( #i#, 3 ) = #modSequence( i, 3 )#<br />
  •  
  • </cfloop>

Here, we're simply encapsulating the details behind a function invocation. When we run the above code we get the following page output:

modSequence( 1, 3 ) = 1
modSequence( 2, 3 ) = 2
modSequence( 3, 3 ) = 3
modSequence( 4, 3 ) = 1
modSequence( 5, 3 ) = 2
modSequence( 6, 3 ) = 3
modSequence( 7, 3 ) = 1
modSequence( 8, 3 ) = 2
modSequence( 9, 3 ) = 3
modSequence( 10, 3 ) = 1
modSequence( 11, 3 ) = 2
modSequence( 12, 3 ) = 3
modSequence( 13, 3 ) = 1
modSequence( 14, 3 ) = 2
modSequence( 15, 3 ) = 3

The modulus operator is pretty awesome, no doubt. Hopefully, I'll now be able to remember how to use it to create a more "standard" repeated sequence. And if I can't, at least I know where to look.




Reader Comments

Aug 10, 2011 at 11:10 AM // reply »
369 Comments

When I first started programming, I thought the MOD operator was the coolest, most awesome and interesting thing. I still love it to this day. Thanks for writing about it. You get extra brownie points, as well, for adding extra math. :-)


Aug 10, 2011 at 1:35 PM // reply »
11,238 Comments

@Anna,

Yeah, the mod operator is totally awesome :) It's one of my favorite operators (which may very well be the geekiest thing I say all day).


Aug 10, 2011 at 3:13 PM // reply »
369 Comments

@Ben,

haha...you can be geeky, that's ok. I am geeky all day, every day, probably, but it's gotten so bad with me, that I don't even really notice it anymore, and don't recognize it when I am.


Aug 10, 2011 at 7:43 PM // reply »
270 Comments

@Ben,

If you cfloop from -6 to 6, instead of from 1 to 15, you'll see that % is actually a remainder operator, not a true modulo. In a true modulo, -5 % 3 would 1, not -2.

It can make a difference if you're trying to generate a random number within a range. Say you want to generate a random number in the range of 0 to 59, to represent the number of seconds to wait before doing something. Ordinarily, % 60 does that quite nicely. But if the first operand accidentally goes negative somehow, you instead get a number in the range of -59 to 0.

Just something to watch out for.


Aug 10, 2011 at 8:02 PM // reply »
270 Comments

This might be a bit more visual. Switching to code for its monofont.

  • Remainder versus true modulo:
  •  
  • i i \ 3 i % 3 true i mod 3
  •  
  • -6 -2 0 0
  • -5 -1 -2 1
  • -4 -1 -1 2
  • -3 -1 0 0
  • -2 0 -2 1
  • -1 0 -1 2
  • 0 0 0 0
  • 1 0 1 1
  • 2 0 2 2
  • 3 1 0 0
  • 4 1 1 1
  • 5 1 2 2
  • 6 2 0 0

You can take integer quotient times divisor and add in the remainder to get the dividend, on either side of 0.

You can't do that with true modulo.


Aug 10, 2011 at 8:03 PM // reply »
270 Comments

Aw, shucks. I wish you would allow pre in addition to code.


Aug 15, 2011 at 11:41 AM // reply »
369 Comments

@Ben, I forgot to mention that I like the other operators, too. It's just that by the time I got to the mod operator, I had used the others so much, I had just grown kind of tired of them. They were kind of like old news at that point. But I still like them. Just think the mod is super-cool. (and can be helpful for a lot of solutions to different problems you can't really solve easily in other ways).


Aug 18, 2011 at 9:41 AM // reply »
158 Comments

We use MOD to place things in row, three columns wide. Thus, if there are eight items, the output ends up looking like:
1 2 3
4 5 6
7 8
is that what prompted this post, Ben?


Oct 29, 2011 at 10:02 PM // reply »
11,238 Comments

@WebManWalking,

It's funny you mention that - I almost never think about numbers in the negative. I know that sounds odd; but, I can't even remember the last time that I really had to work with negative numbers. ... I am sure that is a ridiculous thought - I am sure I use them all the time :)

@Randall,

That's the kind of situation where I really started to use MOD for the first time on a regular basis. When I was using Table tags to lay things out, especially, I remember I used to use the MOD operator to determine where I should add the closing / opening TR tags.


Feb 13, 2013 at 3:22 PM // reply »
17 Comments

Another particularly useful way to use the MOD operator is to break items up into an arbitrary number of columns. Say you have an unknown number of elements and you want to display them in three reasonably even columns, you would divide the number of elements by the number of columns, round up or down (so you're working with an integer), and start a new column when your MODULUS is zero.


Feb 14, 2013 at 9:51 AM // reply »
11,238 Comments

@Paul,

I believe that splitting columns and rows was actually one of the first things I ever used it for in production. I vaguely remember having code like:

  • <tr>
  • <cfloop query="foo">
  •  
  • <td> .. </td>
  •  
  • <cfif ! ( foo.currentRow mod 3 )>
  •  
  • <!-- Start new row. -->
  • </tr><tr>
  •  
  • </cfif>
  •  
  • </cfloop>
  • </tr>

... something like that.


Feb 14, 2013 at 10:38 AM // reply »
17 Comments

@Ben
That's about what the code would look like. I was thinking about, say, three left-floating DIVs with unordered lists containing the items you want to display. In that situation, your modulus divisor is not constant, but calculated based on the number of records.

I suppose you could also do this sort of thing with news articles or classified ads based on the number of "inches" for each article or some other arbitrary unit of measuring length, thus simulating the columnar layout of a newspaper.


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 10:37 PM
Very Simple Pusher And ColdFusion Powered Chat
hi id making plz easy ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
May 15, 2013 at 4:15 PM
What If All User Interface (UI) Data Came In Reports?
@Josh, Thanks! @Ben, I definitely recommend the David West book "Object Thinking" I've been quoting from. It goes deeply into the philosophy and history of OO programming. His breadth ... read »
May 15, 2013 at 11:36 AM
Ask Ben: Print Part Of A Web Page With jQuery
I found this helpfull when you need to keep (refresh) the original parent page after closing the iframe child print dialog (Hoping you're not using a form at this time so it won't submit again): On ... read »
May 14, 2013 at 7:13 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, If there's any books you'd recommend on the subject of domain modelling, I'd love to hear it. I just downloaded the free PDF of "Domain Driven Design Quickly". Figured I'd give it ... read »
May 14, 2013 at 6:57 PM
The UX Of Prototyping: Low-Fidelity Is The New High-Fidelity
@Phillip, I'm not sure I follow what you mean? Are you saying that you looked at the list of widgets provided by the jQuery UI and let that be your style guide? ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools