The Integer Division Operator In ColdFusion
Posted October 11, 2010 at 9:43 AM by Ben Nadel
Last week, I was talking to my esteemed colleague, Ryan Jeffords, about a mathematical expression that used the "\" operator. I had thought that this operator was simply a division operator that had been mistyped. However, it turns out that the backwards-division operator is actually an operator unto itself: integer division. I can't believe I didn't know about one of the core ColdFusion operators. And, to make matters more depressing, it's been available since at least ColdFusion 7 (trying to find livedocs pre-CF7 is not fun).
The integer division operator (\) works by removing the decimal portion from the resultant division value. It's basically like calling the fix() function on the outcome. To demonstrate this integer division operator, take a look at the following ColdFusion code:
- <!--- Standard division operator. --->
- 9.2 / 4 = #(9.2 / 4)#<br />
- -9.2 / 4 = #(-9.2 / 4)#<br />
- <br />
- <!--- Integer division operator. --->
- 9.2 \ 4 = #(9.2 \ 4)#<br />
- -9.2 \ 4 = #(-9.2 \ 4)#<br />
- <br />
- <!--- Standard division with the Fix function. --->
- fix( 9.2 / 4 ) = #fix( 9.2 / 4 )#<br />
- fix( -9.2 / 4 ) = #fix( -9.2 / 4 )#<br />
Here, I am using the standard division operator, the integer division operator, and then a combination of standard division and fix() function. When we run the above code, we get the following output:
9.2 / 4 = 2.3
-9.2 / 4 = -2.3
9.2 \ 4 = 2
-9.2 \ 4 = -2
fix( 9.2 / 4 ) = 2
fix( -9.2 / 4 ) = -2
As you can see, the integer division operator takes the results of standard division and then removes the decimal place. This produces the same result as fix()'ing the standard division result.
As a practical use case for such division, take a look at the following example that combines ColdFusion's modulus operator with the integer division operator:
- <!--- Set a number of minutes that we will break down. --->
- <cfset totalMinutes = 97 />
- Break total minutes down into Hours and Minutes using the
- interger division and the modulus operator respectively.
- #(totalMinutes \ 60)# hours, #(totalMinutes % 60)# minutes
Here, we are breaking the total number of minutes into hours and minutes. Integer-dividing the total minutes by 60 gives us the number of whole hours. And, taking the modulus of 60 gives us the remaining minutes. When we run the above code, we get the following output:
1 hours, 37 minutes
You may notice that I am using % instead of MOD for the modulus operator. When I was looking this integer division operator up in the documentation, I was happy to be reminded that as of ColdFusion 8, the modulus operator can be either MOD or the more programmer-friendly % sign.
I've been a huge fan of the fix() function for the way it cleaves the decimal place from a given number. However, I am sure that I'll now be able to simplify at least some of my code using ColdFusion's integer division operator. Moments like this are always a reminder that it pays to just read the manual.
Very nice! Sad that it took this long to get that in, but way cool to know about it. Thanks for bringing it to my attention Ben!
Heck yeah - I'm pretty exciting about this too.
This is actually a very sexy way to handle something like this.
good to know ... and if anyone ever doubts your 'geekness' simply point them to this post! only a true geek would get uber-excited over something like this. hehe.
Thanks - agreed.
Ha ha, gotta keep my street cred going ;)
I found this by accident one time by using the wrong slash. Spent hours debugging because I want the decimal places LOL.
Another very good piece of information Ben.. Thanks a Lot..
Yes, integer division rounds down any remainder. Which brings up an interesting tangential topic:
Have you ever heard the term "covered quotient"? It refers to an integer division that rounds up any remainder. For example, suppose your parking lot charges $3 an hour or any fraction thereof. If you stay there 61 minutes, you're charged for 2 hours.
If you have an integer division operator, the way to get a covered quotient is to add (divisor - 1) to the dividend, and then divide. So in the case of the parking lot example, the cfscript calculation is as follows:
- Hours = (Minutes + 59) \ 60;
Another interesting tangential topic is the difference between true modulo arithmetic and that performed by computers. Only math majors know the difference, and we long ago gave it up as a lost cause. The difference is apparent when the quotient is negative. In true modulo arithmetic, -3 mod 10 is 7. Computers usually say that it's -3.
Anytime you need more trivia, let me know! :-)
Excellent post. Who would ever guess that such an operator existed. This is something I can use. Thanks for the real life example.
I just want to throw out there that I needed to do integer division the other day and I tried the '\' on a whim. I was really glad to see that it worked, and glad to see the post about it!
Ha ha, I could definitely see this being a source of head-bashing if you had no idea that the operator exists. I could imagine myself just being like, "WTF!! Why aren't you working!!!!!".
Thanks my man.
I have to believe that this "covered quotient" concept was never heard of until cell phone companies and parking garages needed a way to charge people more money :)
In all seriousness, I have never heard of it. Is this something that some languages have an operator for (that you know of)?
As far as the modulus operator, I had no idea that there was even this divergence. In fact, when you get into negative numbers, my understanding of how mod should work definitely becomes a bit fuzzy.
Definitely a cool operator.
I was a systems programmer for quite a while, meaning that for, like, 5 years or more, I coded in nothing but assembly language. One of the things you have to do at the hardware level is allocate blocks of memory or blocks of disk space, both of which occur in multiples of a fixed block size. So if you have something that you have to store somewhere, you have to allocate a covered quotient of the minimum block size.
For example, suppose you have to allocate memory in chunks of 1024 bytes. You have to read a file into memory. Before you begin, you know from the directory entry that the file contains 12345 bytes. How many 1K buffers do you need to allocate to read the file into memory?
(12345 + 1023) \ 1024 = 13 core blocks of 1K each.
The trick of adding (divisor - 1) before doing the integer division comes from the observation that computers do integer arithmetic faster than they do anything else. It's faster to add a constant and divide by a constant (2 instructions) than to divide by a constant and then do a comparison and branch instruction ("if") to determine whether to add 1 to the result (3 or 4 instructions). And yes, assembly language coders really do optimize right down to the number of hardware instructions.
Well anyway, now you know why it's called the "covered quotient". It's the quotient that's sufficient to cover the amount of data you need to hold.
5 years of assembly language?!? And to think I had trouble with one semester of it :) I have to agree, though, assembly programmers definitely do spend a ton of time optimizing the code. I remember one of the most frustrating exercises that we had to do on a regular basis was look at a block of commands and figure out how to arrange them so that we didn't have to use "noop" commands.
That stuff is only a vague memory at this point; but, I remember that some commands took two clock cycles; so, there was opportunity to sneak an unrelated command right after it (to fill up the clock cycle as a more efficient noop).... or something to that effect.
As painful as it was, the assembly teacher was probably one of the happiest teachers that I had in all of my schooling.
This is also a handy shortcut for truncating a real to an int.
adjustedPriceInCents = (priceInCents * discount) \ 1
I'll bet you're keeping all of those rounded-down fractional pennies, aren't-cha. :-)
It's been there since at least version 2.0 (the first version I used). Like some of the other commenters, I discovered it accidentally while working on my first CF app :)
Yeah, assembler and FORTRAN (and a bunch of other languages) have integer division. It is one of several gotchas on old FORTRAN tests. They slipped in integer division and those who didn't pay attention always got weird results that took a lot of hair pulling time to figure out. It is very powerful when you need it.
Roland's right. Integer division has been in CF for a long time.
The biggest thing I got out of taking the CF certified developer's test was studying for it. That's where you pick up on things you don't commonly use and may have slipped under your radar.
On the subject of operators, there are also a bunch of bit operators that most people ignore or are unaware of, that may be useful in certain circumstances. In particular, you can use each bit of a 32-bit integer to represent a day of the month, for example. I've used that capability in scheduling apps. Or you can use it to keep a bunch of boolean options in only one database column and not have to keep making requests of your database group for more columns all the time. In a sense, days of the month, represented as bits, are an example of many booleans. It's a space versus time trade-off.
Just tossing that out there as an idea.
Ha ha, this must be how the scam in Office Space worked - integer division :)
Dangy! for that long? I must have seen it before then, but probably didn't have enough of an understanding of programming at the time to see why something like this would be useful. I know I'll never forget it now.
I always find those kinds of tests sneaky. The CF7 certification test had lots of questions like - When you run this code, what will happen? It's odd because it's such a different mindset than writing code. But speaking to @Steve's point, having to prepare for tests like that definitely forces you to learn about aspects of the language that you might have been aware of.
Bits as days - very interesting! Bit-wise operations are one of those things that I feel I need to "dust off" every time I try to use them. For some reason, that kind of logic won't cement in my head over the long term.