Add st, nd, rd and th (ordinal) suffix to a number
The rules are as follows:
- st is used with numbers ending in 1 (e.g. 1st, pronounced first)
- nd is used with numbers ending in 2 (e.g. 92nd, pronounced ninety-second)
- rd is used with numbers ending in 3 (e.g. 33rd, pronounced thirty-third)
- As an exception to the above rules, all the "teen" numbers ending with 11, 12 or 13 use -th (e.g. 11th, pronounced eleventh, 112th, pronounced one hundred [and] twelfth)
- th is used for all other numbers (e.g. 9th, pronounced ninth).
The following JavaScript code (rewritten in Jun '14) accomplishes this:
function ordinal_suffix_of(i) { var j = i % 10, k = i % 100; if (j == 1 && k != 11) { return i + "st"; } if (j == 2 && k != 12) { return i + "nd"; } if (j == 3 && k != 13) { return i + "rd"; } return i + "th";}
Sample output for numbers between 0-115:
0 0th 1 1st 2 2nd 3 3rd 4 4th 5 5th 6 6th 7 7th 8 8th 9 9th 10 10th 11 11th 12 12th 13 13th 14 14th 15 15th 16 16th 17 17th 18 18th 19 19th 20 20th 21 21st 22 22nd 23 23rd 24 24th 25 25th 26 26th 27 27th 28 28th 29 29th 30 30th 31 31st 32 32nd 33 33rd 34 34th 35 35th 36 36th 37 37th 38 38th 39 39th 40 40th 41 41st 42 42nd 43 43rd 44 44th 45 45th 46 46th 47 47th 48 48th 49 49th 50 50th 51 51st 52 52nd 53 53rd 54 54th 55 55th 56 56th 57 57th 58 58th 59 59th 60 60th 61 61st 62 62nd 63 63rd 64 64th 65 65th 66 66th 67 67th 68 68th 69 69th 70 70th 71 71st 72 72nd 73 73rd 74 74th 75 75th 76 76th 77 77th 78 78th 79 79th 80 80th 81 81st 82 82nd 83 83rd 84 84th 85 85th 86 86th 87 87th 88 88th 89 89th 90 90th 91 91st 92 92nd 93 93rd 94 94th 95 95th 96 96th 97 97th 98 98th 99 99th100 100th101 101st102 102nd103 103rd104 104th105 105th106 106th107 107th108 108th109 109th110 110th111 111th112 112th113 113th114 114th115 115th
From Shopify
function getNumberWithOrdinal(n) { var s = ["th", "st", "nd", "rd"], v = n % 100; return n + (s[(v - 20) % 10] || s[v] || s[0]);}[-4,-1,0,1,2,3,4,10,11,12,13,14,20,21,22,100,101,111].forEach( n => console.log(n + ' -> ' + getNumberWithOrdinal(n)));
Minimal one-line approach for ordinal suffixes
function nth(n){return["st","nd","rd"][((n+90)%100-10)%10-1]||"th"}
(this is for positive integers, see below for other variations)
Explanation
Start with an array with the suffixes ["st", "nd", "rd"]
. We want to map integers ending in 1, 2, 3 (but not ending in 11, 12, 13) to the indexes 0, 1, 2.
Other integers (including those ending in 11, 12, 13) can be mapped to anything else—indexes not found in the array will evaluate to undefined
. This is falsy in javascript and with the use of logical or (|| "th"
) the expression will return "th"
for these integers, which is exactly what we want.
The expression ((n + 90) % 100 - 10) % 10 - 1
does the mapping. Breaking it down:
(n + 90) % 100
: This expression takes the input integer − 10 mod 100, mapping 10 to 0, ... 99 to 89, 0 to 90, ..., 9 to 99. Now the integers ending in 11, 12, 13 are at the lower end (mapped to 1, 2, 3).- 10
: Now 10 is mapped to −10, 19 to −1, 99 to 79, 0 to 80, ... 9 to 89. The integers ending in 11, 12, 13 are mapped to negative integers (−9, −8, −7).% 10
: Now all integers ending in 1, 2, or 3 are mapped to 1, 2, 3. All other integers are mapped to something else (11, 12, 13 are still mapped to −9, −8, −7).- 1
: Subtracting one gives the final mapping of 1, 2, 3 to 0, 1, 2.
Verifying that it works
function nth(n){return["st","nd","rd"][((n+90)%100-10)%10-1]||"th"}//test integers from 1 to 124for(var r = [], i = 1; i < 125; i++) r.push(i + nth(i));//output resultdocument.getElementById('result').innerHTML = r.join('<br>');
<div id="result"></div>
Variations
Allowing negative integers:
function nth(n){return["st","nd","rd"][(((n<0?-n:n)+90)%100-10)%10-1]||"th"}
In ES6 fat arrow syntax (anonymous function):
n=>["st","nd","rd"][(((n<0?-n:n)+90)%100-10)%10-1]||"th"
Update
An even shorter alternative for positive integers is the expression
[,'st','nd','rd'][n%100>>3^1&&n%10]||'th'
See this post for explanation.
Update 2
[,'st','nd','rd'][n/10%10^1&&n%10]||'th'