Coder Perfect

Is it possible to build ordinals in C# with ease?


Is there an easy way in C# to create Ordinals for a number? For example:

Is it possible to achieve this using String.Format() or are there any other functions?

Asked by GateKiller

Solution #1

This page contains a comprehensive summary of all number formatting rules:

Number format strings that are unique to you

As you can see, there’s nothing in there concerning ordinals, therefore String.Format won’t work. However, writing a function to accomplish this is not difficult.

public static string AddOrdinal(int num)
    if( num <= 0 ) return num.ToString();

    switch(num % 100)
        case 11:
        case 12:
        case 13:
            return num + "th";

    switch(num % 10)
        case 1:
            return num + "st";
        case 2:
            return num + "nd";
        case 3:
            return num + "rd";
            return num + "th";

Update: Ordinals don’t exist for = 0, so the code above has been modified. The ToString() functions were also deprecated.

It’s also worth noting that this isn’t internationalized. I’m not sure how ordinals work in other languages.

Answered by samjudson

Solution #2

Remember internationalisation!

The solutions presented here are solely applicable to English. When you need to support different languages, things grow a lot more complicated.

For example, depending on whether the thing you’re counting is masculine, feminine, or plural, “first” in Spanish would be written as “1.o”, “1.a”, “1.os”, or “”!

If your software needs to handle multiple languages, ordinals should be avoided.

Answered by roomaroo

Solution #3

Jesse’s version of Stu’s and samjudson’s versions are mine:)

A unit test is included to demonstrate that the accepted response is erroneous when the number is less than one.

/// <summary>
/// Get the ordinal value of positive integers.
/// </summary>
/// <remarks>
/// Only works for english-based cultures.
/// Code from:
/// With help:
/// </remarks>
/// <param name="number">The number.</param>
/// <returns>Ordinal value of positive integers, or <see cref="int.ToString"/> if less than 1.</returns>
public static string Ordinal(this int number)
    const string TH = "th";
    string s = number.ToString();

    // Negative and zero have no ordinal representation
    if (number < 1)
        return s;

    number %= 100;
    if ((number >= 11) && (number <= 13))
        return s + TH;

    switch (number % 10)
        case 1: return s + "st";
        case 2: return s + "nd";
        case 3: return s + "rd";
        default: return s + TH;

public void Ordinal_ReturnsExpectedResults()
    Assert.AreEqual("-1", (1-2).Ordinal());
    Assert.AreEqual("0", 0.Ordinal());
    Assert.AreEqual("1st", 1.Ordinal());
    Assert.AreEqual("2nd", 2.Ordinal());
    Assert.AreEqual("3rd", 3.Ordinal());
    Assert.AreEqual("4th", 4.Ordinal());
    Assert.AreEqual("5th", 5.Ordinal());
    Assert.AreEqual("6th", 6.Ordinal());
    Assert.AreEqual("7th", 7.Ordinal());
    Assert.AreEqual("8th", 8.Ordinal());
    Assert.AreEqual("9th", 9.Ordinal());
    Assert.AreEqual("10th", 10.Ordinal());
    Assert.AreEqual("11th", 11.Ordinal());
    Assert.AreEqual("12th", 12.Ordinal());
    Assert.AreEqual("13th", 13.Ordinal());
    Assert.AreEqual("14th", 14.Ordinal());
    Assert.AreEqual("20th", 20.Ordinal());
    Assert.AreEqual("21st", 21.Ordinal());
    Assert.AreEqual("22nd", 22.Ordinal());
    Assert.AreEqual("23rd", 23.Ordinal());
    Assert.AreEqual("24th", 24.Ordinal());
    Assert.AreEqual("100th", 100.Ordinal());
    Assert.AreEqual("101st", 101.Ordinal());
    Assert.AreEqual("102nd", 102.Ordinal());
    Assert.AreEqual("103rd", 103.Ordinal());
    Assert.AreEqual("104th", 104.Ordinal());
    Assert.AreEqual("110th", 110.Ordinal());
    Assert.AreEqual("111th", 111.Ordinal());
    Assert.AreEqual("112th", 112.Ordinal());
    Assert.AreEqual("113th", 113.Ordinal());
    Assert.AreEqual("114th", 114.Ordinal());
    Assert.AreEqual("120th", 120.Ordinal());
    Assert.AreEqual("121st", 121.Ordinal());
    Assert.AreEqual("122nd", 122.Ordinal());
    Assert.AreEqual("123rd", 123.Ordinal());
    Assert.AreEqual("124th", 124.Ordinal());

Answered by si618

Solution #4

Simple, clean, quick

private static string GetOrdinalSuffix(int num)
    if (num.ToString().EndsWith("11")) return "th";
    if (num.ToString().EndsWith("12")) return "th";
    if (num.ToString().EndsWith("13")) return "th";
    if (num.ToString().EndsWith("1")) return "st";
    if (num.ToString().EndsWith("2")) return "nd";
    if (num.ToString().EndsWith("3")) return "rd";
    return "th";

Or, better yet, as a method of extension

public static class IntegerExtensions
    public static string DisplayWithSuffix(this int num)
        if (num.ToString().EndsWith("11")) return num.ToString() + "th";
        if (num.ToString().EndsWith("12")) return num.ToString() + "th";
        if (num.ToString().EndsWith("13")) return num.ToString() + "th";
        if (num.ToString().EndsWith("1")) return num.ToString() + "st";
        if (num.ToString().EndsWith("2")) return num.ToString() + "nd";
        if (num.ToString().EndsWith("3")) return num.ToString() + "rd";
        return num.ToString() + "th";

Simply dial

int a = 1;

or as straightforward as


Answered by Shahzad Qureshi

Solution #5

It’s up to you to make your own dice. To give you an idea , what I’m thinking about right now:

public static string Ordinal(this int number)
  var work = number.ToString();
  if ((number % 100) == 11 || (number % 100) == 12 || (number % 100) == 13)
    return work + "th";
  switch (number % 10)
    case 1: work += "st"; break;
    case 2: work += "nd"; break;
    case 3: work += "rd"; break;
    default: work += "th"; break;
  return work;

After that, you’re free to go.


Exceptions were added on 11/12/13. On the spur of the moment, I said:-)

Edited for 1011 — others have already addressed this; I simply want to make sure no one else gets this wrong version.

Answered by Stu

Post is based on