Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Counting numbers in english 10

Status
Not open for further replies.

BabyJeffy

Programmer
Sep 10, 2003
4,189
GB
The way we count numbers in English appears quite strange (I am sure) to those who don't speak it natively. When we refer to dates we often add "st", "rd", "nd" or "th" to the end of any numbers. Example: 10th February, 23rd June

I remember one solution I used for solving this "problem" early in my career. There can be up to 31 days in a month, so I created an array and populated it with the correct endings:
Code:
var numberWords = ['X','st','nd','rd','th','th','th','th','th','th','th','th','th','th',
'th','th','th','th','th','th','th','st','nd','rd','th','th','th','th','th','th','th','st'];
And I would then get the correct ending by calling the index of the array with the number directly:
Code:
function getNumberExt(theNumber) {
  return (theNumber+numberWords[theNumber]);
}
alert(getNumberExt(23)); // alerts 23rd
My example contains no attempt at error checking (and this is certainly not appropriate for production quality code).

I've used much the same code server-side as well as client-side and it's done the job well. I am interested in how others have achieved a similar result.

Does anyone have any significantly different mechanisms to do this? Want to share?

Cheers,
Jeff

[tt]Jeff's Page [/tt][tt]@[/tt][tt] Code Couch
[/tt]

What is Javascript? faq216-6094
 
Jeff,

You can use some pretty simple rules for this:

If the number ends in 1, the suffix always "st"
If the number ends in 2, the suffix always "th"
If the number ends in 3, the suffix always "rd"
If the number is 11, 12, 13, or anything else, the suffix is always "th".

Of course, the "11, 12, 13" rule should be tested after the first 3 ;o)

Dan
 
I might approach it this way:
Since there are only 4 potential matches, I would just pull the last digit off the number match numbers 1-3 or default to th.
Code:
function getNumberExt(theNumber) {
  var endnum = theNumber.charAt(theNumber.length-1);
  switch (endnum) {
    case '1': var endtag = "st"; break;
    case '2': var endtag = "nd"; break;
    case '3': var endtag = "rd"; break;
  default: var endtag = 'th';
  }
  alert(endnum+endtag);
}

I do not think there is much difference in efficiency but it saves a small amount of resources not having an array in memory.


Paranoid? ME?? WHO WANTS TO KNOW????
 
Damn, I missed out on the 11,12,13. :)

Paranoid? ME?? WHO WANTS TO KNOW????
 
OK, this is quick and crude but...
Code:
function getNumberExt(theNumber) {
  var endnum = theNumber.charAt(theNumber.length-1);
  switch (endnum) {
    case '1': var endtag = "st"; break;
    case '2': var endtag = "nd"; break;
    case '3': var endtag = "rd"; break;
  default: var endtag = 'th';
  }
  endtag = (theNumber.substring(theNumber.length-2,2) == 11 || theNumber.substring(theNumber.length-2,2) == 12 || theNumber.substring(theNumber.length-2,2) == 13)?'th':endtag; 
  alert(theNumber+endtag);
}

Paranoid? ME?? WHO WANTS TO KNOW????
 
Nice - I like the idea of testing the digits like that... very different to my old approach. I was thinking it'd be a good chance to play with the mod operator - just have to figure out how [smile]

Cheers,
Jeff

[tt]Jeff's Page [/tt][tt]@[/tt][tt] Code Couch
[/tt]

What is Javascript? faq216-6094
 
Or:
Code:
function getNumberExt(theNumber) {
  var endnum = (theNumber.length > 1)?theNumber.substring(theNumber.length-2,2):theNumber.charAt(theNumber.length-1);
  switch (endnum) {
    case '1': var endtag = "st"; break;
    case '2': var endtag = "nd"; break;
    case '3': var endtag = "rd"; break;
    case '11': var endtag = "th"; break;
    case '12': var endtag = "th"; break;
    case '13': var endtag = "th"; break;
  default: var endtag = 'th';
  }
  alert(theNumber+endtag);
}

Paranoid? ME?? WHO WANTS TO KNOW????
 
or for even less typing:
Code:
function getNumberExt(theNumber) {
  var endnum = (theNumber.length > 1)?theNumber.substring(theNumber.length-2,2):theNumber.charAt(theNumber.length-1);
  switch (endnum) {
    case '1': var endtag = "st"; break;
    case '2': var endtag = "nd"; break;
    case '3': var endtag = "rd"; break;
    case '11':
    case '12':
    case '13': var endtag = 'th';
    default: var endtag = 'th';
  }
  alert(theNumber+endtag);
}

-kaht

How much you wanna make a bet I can throw a football over them mountains?
sheepico.jpg
 
I did not know a case statement would cascade down that way, good to know.

Paranoid? ME?? WHO WANTS TO KNOW????
 
yeah, as long as it doesn't hit a break statement

-kaht

How much you wanna make a bet I can throw a football over them mountains?
sheepico.jpg
 
er...the code above doesn't work!

It caters for 11th, 12th and 13th, but not 21st, 22nd, 23rd, 31st, 32nd, etc...try this:

Code:
function getNumberExt(theNumber) {

  var endnum = (theNumber.substring(theNumber.length-2,1) == '1') ? theNumber.substring(theNumber.length-2,2):theNumber.charAt(theNumber.length-1);

  switch (endnum) {
    case '1': var endtag = "st"; break;
    case '2': var endtag = "nd"; break;
    case '3': var endtag = "rd"; break;
    default: var endtag = 'th';
  }
  alert(theNumber+endtag);
}

<marc>
New to Tek-Tips? Get better answers - faq581-3339
 
or: slightly more optimised version ;)
Code:
  [COLOR=green]// replace[/color]
  var endnum = (theNumber.substring(theNumber.length-2,1) == '1') ? theNumber.substring(theNumber.length-2,2):theNumber.charAt(theNumber.length-1);

  [COLOR=green]// with[/color]
  var endnum = (theNumber.charAt(theNumber.length-2) == '1') ? "0" :  theNumber.charAt(theNumber.length-1);

<marc>
New to Tek-Tips? Get better answers - faq581-3339
 
kaht,

Put your 11/12/13 ABOVE the 1/2/3 and add a break to them, or else when the number is 11, the case 1 will take over.

Still, we seem to be forgetting that 111,112, and 113, 211, 212, 213, ... all need to be checked.

--Dave


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
O Time, Strength, Cash, and Patience! [infinity]
 
we seem to be forgetting that 111,112, and 113, 211, 212, 213, ... all need to be checked.

...or maybe not. I didn't look at everybody's post so closely. I can see that it is accounted for in some of them.

Dave


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
O Time, Strength, Cash, and Patience! [infinity]
 
I just copied/pasted from nightowl's solution. At a quick glance I'm pretty sure his ternary operation should prevent endnum from being '1' when it's supposed to be '11'. Therefore, 11 is safe from the case of '1'.

(although I'll give the disclaimer that I still haven't tested any of the code, heh)

-kaht

How much you wanna make a bet I can throw a football over them mountains?
sheepico.jpg
 
kaht, the problem with the code is the conditional:
Code:
var endnum = (theNumber.length > 1)?
If the number is 2 digits or longer, use the last 2 digits. If it's only a single digit, use that single digit.

Whilst this allows the first 2 digit numbers - 11, 12, and 13, it doesn't cater for 21, 22, 31, 32, 101, etc.

I use the conditional:
Code:
var endnum = (theNumber.charAt(theNumber.length-2) == '1')
If the 10s unit is '1', use a default exception ("0"), otherwise, use the last digit.

<marc>
New to Tek-Tips? Get better answers - faq581-3339
 
niteowl said:
function getNumberExt(theNumber) {
var endnum = theNumber.charAt(theNumber.length-1);
switch (endnum) {
case '1': var endtag = "st"; break;
case '2': var endtag = "nd"; break;
case '3': var endtag = "rd"; break;
default: var endtag = 'th';
}
endtag = (theNumber.substring(theNumber.length-2,2) == 11 || theNumber.substring(theNumber.length-2,2) == 12 || theNumber.substring(theNumber.length-2,2) == 13)?'th':endtag;
alert(theNumber+endtag);
}

You can use mod in place of the last endtag statement to good effect.

Code:
if(theNumber%100 >= 11 && theNumber%100 <= 13) endtag = "th";

--Dave


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
O Time, Strength, Cash, and Patience! [infinity]
 
coolness!

Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"[URL unfurl="true"]http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">[/URL]

<html>
<head>
<title>Untitled</title>
</head>

<body>

<script type="text/javascript"><!--
for ( var i = 1; i < 151; i++ ) {
    var intSingleDidget = i%10;
    var intTwoDidget = i%100;
    var blnIsTeen = (intTwoDidget<20&&intTwoDidget>10);
    var strOutput;
    strOutput = i + ((intSingleDidget==1&&!blnIsTeen)?"st":((intSingleDidget==2&&!blnIsTeen)
?"nd":((intSingleDidget==3&&!blnIsTeen)?"rd":"th")));
    document.writeln(strOutput + "<br />");
}
//--></script>

</body>
</html>

*cLFlaVA
----------------------------
[tt]I already made like infinity of those at scout camp...[/tt]
beware of active imagination: [URL unfurl="true"]http://www.coryarthus.com/[/url]

BillyRayPreachersSonIsTheLeetestHax0rDude
[banghead]
 
with less-meaningful variable names:

Code:
<script type="text/javascript"><!--
for ( var i = 1; i < 151; i++ ) {
    var s = i%10;
    var t = i%100;
    var y = (t<20&&t>10);
    var o;
    o = i + ((s==1&&!y)?"st":((s==2&&!y)?"nd":((s==3&&!y)?"rd":"th")));
    document.writeln(o + "<br />");
}
//--></script>

*cLFlaVA
----------------------------
[tt]I already made like infinity of those at scout camp...[/tt]
beware of active imagination: [URL unfurl="true"]http://www.coryarthus.com/[/url]

BillyRayPreachersSonIsTheLeetestHax0rDude
[banghead]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top