|
YOUR FEEDBACK
Did you read today's front page stories & breaking news?
SYS-CON.TV SYS-CON.TV WEBCASTS |
TOP COLDFUSION LINKS Playing with Numbers
It's all in the math
By: Simon Horwith
Jan. 18, 2005 12:00 AM
For this month's installment, I thought I'd return the Community column to its original roots ("Tales From the List") and focus on a recent thread in the CFDJ List. Brian Simpson wrote to the List posing the following problem: "How do I round to the nearest 'x'?" Specifically, Brian has a client that wants to be able to use its e-commerce application to reduce all of their product prices by 10% and then round up to the nearest number evenly divisible by 50. Before you read on, ask yourself how you would achieve this task. It's not as easy as you'd think...or is it? The first response Brian received was from Evik. He suggested removing any decimal values (cents) and then treating the number as a string. If the last two characters have a numeric value in the range from 1-50, then make the last two characters 50. If the last two characters have a numeric value in the range 51-99, then make the last two numbers 00 and then add 100 to the number. The code, written in a <CFSCRIPT> function, to do this would look like the following:
<cfscript>
function roundToNext50(theNum){
var retVal = 0;
var someNum = 0;
if (len(theNum) is 1){
retVal = 50;
} else {
someNum = val(right(theNum, 2));
}
if (not retVal){
if (someNum gt 50){
if (len(theNum) is 2){
retVal = 100;
} else {
retVal = 100 + val(left(theNum, len(theNum) - 2) & "00");
}
} else {
if (right(theNum, 2)){
retVal = val(left(theNum, len(theNum) - 2) & "50");
} else {
retVal = theNum;
}
}
}
return retVal;
}
</cfscript>
This is not terribly pretty code - I certainly wouldn't want to have to make this function flexible enough to support rounding up to a dynamic increment. That said, it will round any number not already divisible by 50 to the next number that is divisible by 50. There are plenty of other ways to write the code to treat a number as a string and round it to the next 50 - this is just one of them. A regular on the CFDJ List, Dave (from TheaterMania), then responded with an elegant solution that surprised everyone. He simply states, "What I do is divide by the rounding increment, round up to the nearest integer, then multiply by the rounding increment." So you divide your number by 50, use ceiling to round it up, then multiply by 50. Presto! You have your next number divisible by 50. The code for this, written in a <CFSCRIPT> function, would look like this:
<cfscript>
function roundToNext50(theNum){
return ceiling(theNum/50)*50;
}
</cfscript>
Quite a difference in the amount of code between the two, isn't there? What's more, this last technique is extremely flexible - add a second argument and you can now round to the next highest number evenly divisible by any increment you want, like so:
<cfscript>
function roundToNextNum(theNum,theIncrement){
return ceiling(theNum/theIncrement)*theIncrement;
}
</cfscript>
I chose to discuss this thread because it illustrates a very important concept. Not just an algebraic concept, but also a development concept. Anytime your immediate solution to a business logic problem involves treating a number as a string, stop and ask yourself whether or not there's a way to achieve your objective using math functions. There almost always is - and it's almost always more elegant. Note that I said business logic problem. Treating a number as a string in presentation-tier code is certainly a safe (and sometimes necessary) practice. If your math skills aren't up to snuff or you're unsure how to write an algorithm to achieve the results you want, send an e-mail to one of the list servers - you're almost always sure to get decent help. CFDJ LATEST STORIES . . .
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS MOST READ THIS WEEK |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||