And On The Seventh Row, MOD Created 1, And It Was Good

Posted April 30, 2007 at 8:54 AM

Tags: ColdFusion

On Ray's Friday Puzzler, it came up that not everyone knows what the MOD (or Modulus) operator is in math. This is one of those things that once you know it, you can't imagine how you lived with out it. The MOD operator does a fairly simple thing: it divides two numbers and returns only the remainder.

To demonstrate how this works in a practical sense, let's run this code:

 Launch code in new window » Download code as text file »

  • <!--- Loop over value range. --->
  • <cfloop
  • index="intValue"
  • from="1"
  • to="15"
  • step="1">
  •  
  • <!---
  • Get the result of this Value MOD'ed by 3.
  • Remember, this will divide 3 into the value
  • and return the remainder.
  • --->
  • #intValue# MOD 3 = #(intValue MOD 3)#<br />
  •  
  • </cfloop>

Running the above code, we get:

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

Notice that we can see a sequence coming through: 1,2,0. The sequence is as long as the number we are using to MOD. This is because every Nth value should be evenly divisible by (N) and then the remainder gets "reset."

This can be a headache saver for ColdFusion query output when you want to format alternating rows. To figure out which row you are on (odd vs. even), all you have to do is MOD the current row by 2. If 2 divides evenly into the row number (and thereby resulting in a remainder of zero), we are on an even row. If we MOD by 2 and have a remainder, we must be on an odd row.

 Launch code in new window » Download code as text file »

  • <!--- Loop over query. --->
  • <cfloop query="qData">
  •  
  • Row #qData.CurrentRow# is:
  •  
  • <!---
  • Check to see if this row is even or odd.
  • If this row number MOD 2 has a reminader
  • (evaluates to TRUE in ColdFusion), then
  • we are in an odd row.
  • --->
  • <cfif (qData.CurrentRow MOD 2)>
  •  
  • ODD
  •  
  • <cfelse>
  •  
  • EVEN
  •  
  • </cfif>
  •  
  • </cfloop>

Running the above, we get:

Row 1 is: ODD
Row 2 is: EVEN
Row 3 is: ODD
Row 4 is: EVEN
Row 5 is: ODD
Row 6 is: EVEN

Tons of stuff has been written about the Modulus operator. It's totally awesome. When working on Ray's puzzler, I was having a huge mental block trying to figure out how to get rid of the zero in my sequence. Here is a great resource I found that talks about using and manipulating sequences using the modulus operator.

Go forth and MOD.

Download Code Snippet ZIP File

Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page





Reader Comments

Apr 30, 2007 at 9:29 AM // reply »
6 Comments

GREAT headline.

Btw, I never got to comment on your issues with being a senior programmer. I am not sure what that means given my being self employed or working for interweb startups and small dev companies for the last 10 years. But I have been reading your blog for the last 4-5 months and I can truthfully say that you are a damn good programmer. You have taught me quite a bit.


Apr 30, 2007 at 9:32 AM // reply »
43 Comments

Another handy use: creating a specific number of columns. I use this all the time since I find myself creating "sets" of checkboxes. If I have 11 checkboxes it's easier to read if they're laid out so that there are 2 rows of 4 and one row of 3.

To do that, I usually give the parent element a pre-defined width and float it to the left. Each successive checkbox then is added to a single row. I can then just test the current index MOD 4 (current index % 4 in php and others) and, if the value is 1, set the element class to "startrow" or some such. To that class I apply clear: left to force the creation of a new row.

As you say...handy.


Apr 30, 2007 at 9:47 AM // reply »
6,516 Comments

@Cozmo,

Thanks for the kind words. Glad that I can help out.

@Rob,

Yeah, excellent use case. Along those same lines, outputting over a calendar can be quite helpful (MOD 7).


Apr 30, 2007 at 10:12 AM // reply »
56 Comments

@ben,

learned this trick a LOOOONG time ago:

Instead of using MOD to find out if a number is ODD or EVEN, use BITAND(). An example:

BitAnd(8,1) would return 0 which means it's EVEN
BitAnd(5,1) woudl return 1 which means it's ODD

Using the MOD function, CF must internally perform a lot of calculations in order to see if there is a remainder or not. BitAnd just uses BitWise logic to see if the number's first bit is a 0 or 1.

I doubt you will see a performance difference on small sites, but if your pumping out 10,000 could make a difference.


Apr 30, 2007 at 10:15 AM // reply »
76 Comments

Using mod is much better than the:

[cfif color is "white"]
[cfset color = "gray"]
[cfelse]
[cfset color = "white"]
[/cfif]

[tr bgcolor = "#color#"]

that I've seen in places...

BTW, I loved the headline too


Apr 30, 2007 at 10:16 AM // reply »
76 Comments

Tony - great idea!


Apr 30, 2007 at 10:43 AM // reply »
6,516 Comments

@Tony,

That is very slick! Bit manipulation is one of those dark arts that I think very few people (including myself) really understand how to take advantage of. I have used Bits as a way to group "flags" for objects, but nothing like this.

Thanks for the awesome tip. And yes, I can see this would be a much better performance feature (as division never actually needs to take place). Cool!


Apr 30, 2007 at 2:29 PM // reply »
56 Comments

thanks for props guys.

But like most of the cool ideas in my head, they all have an originating source, though most of the time I don't remember where :P

Is a discussion on the CF Cookbook about this topic:

http://www.coldfusioncookbook.com/entry/53/How-do-I-determine-if-a-number-is-even-or-odd


Apr 30, 2007 at 2:58 PM // reply »
6,516 Comments

@Tony,

You might not have invented it, but you sure get credit for pointing it out to me:

http://www.bennadel.com/index.cfm?dax=blog:668.view

:)


Nov 25, 2007 at 3:06 PM // reply »
1 Comments

There is a faster way to do Even/Odd checks

int OMask = 1;

if( (someotherint & OMask) == OMask)
numberisodd
else
numberiseven

-Chris


Nov 25, 2007 at 4:04 PM // reply »
6,516 Comments

@Chris,

There is no bit-wise AND operator in ColdFusion. Instead, you would have to use the BitAnd() method:

<cfif BitAnd( qData.CurrentRow, 1 )>
... ODD ...
<cfelse>
... EVEN ...
</cfif>

As far as this method being faster, I suppose it would be because it's not actually performing any mathematical dvision (as would be required for MOD). Really, we are just taking the binary representation of the number and examining the first digit. I assume that this would be a constant speed no matter how large the number. Thanks for the good tip.


Jun 30, 2009 at 1:01 PM // reply »
18 Comments

I just wrote something similar before stumbling upong this post. I had a hard time deciphering MOD so I made this script so I could see how it works visually.

<cfloop from="1" to="10" index="i">
<cfoutput>
<h3>MOD #i#</h3>
<cfloop from="1" to="10" index="z">
<cfset res = z MOD i />
<li>#z# MOD #i# = #res#</li>
</cfloop>
</cfoutput>
</cfloop>

I was trying to get it to execute on the third iteration. What I found is doing x MOD y = 0, where y is your desired iteration (in my case 3) seems to work in any case. Run the code and see for yourself!


Jun 30, 2009 at 1:33 PM // reply »
6,516 Comments

@Will,

I am not sure what you mean?


Jun 30, 2009 at 4:29 PM // reply »
18 Comments

I'm referring to using MOD in a cfoutput query, where you'd need every other row highlighting, or a line break after every third item, or fifth. I've found the easiest and most legible way is to do :
currentRow MOD 2 EQ 0
or
currentRow MOD 3 EQ 0
or currentRow MOD 5 EQ 0 respectively.

The only need I've had for MOD thus far has been in a query loop, so I guess it's a narrow perspective.


Jul 1, 2009 at 8:23 AM // reply »
6,516 Comments

@Will,

Ahh, gotcha. Yeah, I think that's how most people need to use MOD. The only time I've had to use it otherwise is for sequential number outputs of some sort.


Post Comment  |  Ask Ben

Recent Blog Comments
Nov 22, 2009 at 1:56 AM
Learning ColdFusion 9: Using CFQuery In CFScript Can Enable SQL Injection Attacks
Why adobe would give you script equivalent of cfquery is beyond me. I love cfquery tag because it helps me wriite clean sql, and get away from the horrible jdbc queries If I wanted to write javali ... read »
Nov 22, 2009 at 1:45 AM
Streaming Text Using ColdFusion's CFContent Tag And The Variable Attribute
The reason you would want to do this is to stream. Ack json/xml files to ria clients I used thus technique before because putting json in response stream causes debugging info to come thru As well a ... read »
Nov 21, 2009 at 6:47 PM
Hal Helms - Real World Object Oriented Development, Sarasota - Day Five
@charlie griefer, Thank you.. ... read »
Nov 21, 2009 at 5:15 PM
Using ColdFusion Structures To Remove Duplicate List Values
@Jose Galdamez, Oh heh yeah I didn't paste the whole code. I should have defined the vars -- my bad. It's fixed thou. Thanks. ... read »
Nov 21, 2009 at 4:49 PM
Styling The ColdFusion 8 WriteToBrowser CFImage Output
Great work yet again Ben! Whilst I didn't use this whole code, I copied some of your regex code for a similar problem with the lack of an alt attribute and unescaped ampersands in CFIMAGE for Railo 3 ... read »
Nov 21, 2009 at 1:13 PM
My First ColdFusion Builder Extension - Encrypting And Decrypting CFM / CFC Files
@Ben, Because I am pedantic, I just want to make sure that everyone knows there is absolutely no encryption going on. There is only encoding and obfuscation. The cfencode tool only obfuscates your C ... read »
Nov 21, 2009 at 12:28 PM
Using ColdFusion Structures To Remove Duplicate List Values
@Jody I can't seem to get your code sample to work. If you are still having problems, try this code out and see if it gets you what you wanted. <!--- Comma delimited list with various duplicates ... read »
Nov 21, 2009 at 11:03 AM
Groovy Operator Overloading Does Not Work In The ColdFusion Context
Hi Ben, Thanks for this informative post. Now I am reading ur old posts too ... read »