I am looking for a solution that is somewhat related to Is there an easy way to create ordinals in C#? , but the inverse.
I would like to automate the following conversions:
First --> 1st
Second --> 2nd
Third --> 3rd
Ninety ninth --> 99th and so on.
I am looking for a solution that is somewhat related to Is there an easy way to create ordinals in C#? , but the inverse.
I would like to automate the following conversions:
First --> 1st
Second --> 2nd
Third --> 3rd
Ninety ninth --> 99th and so on.
Generally, this is most easily done by parsing the number using a dictionary of number words. The rules are:
Convert the string to lower-case, and split the string into words based on spaces, commas and/or dashes. Remove empty entries (which correspond to adjacent multiple delimiters).
Start with the first word of the string. That should be a word corresponding to one of the first nineteen natural numbers - "one", "two", "three", ..., "seventeen", "eighteen", "nineteen" - or a multiple of ten from "twenty" to "ninety". Remember that because you must consider ordinals, the number words you are looking for are both of the previous form AND the form ending in "st", "nd", "rd", or "th"; the different is that if you see the ordinal version of any word, you should be done. In any case, after having looked up the number word (and hopefully found a value) in a predefined Dictionary<string, int> containing your number words and corresponding values, remember this number as your "working value".
Now start iterating through words. If the next word is also one of these natural number words, add it to the value of the "working value", but don't add the value to the "running total".
If the next word is an order-of-magnitude indicator (hundred, thousand, million, billion, trillion), multiply your working value by the order of magnitude. Then, "peek" at the next word; if it is also an OOM word (the main one's "hundred thousand", but British English also allows "thousand million" as a synonym for what we know as "billion", and some really large spoken numbers can be said with repeating smaller OOMs like "million million million"), keep what you have and continue iterating; otherwise, add your current working value to the running total, and zero your working value before moving on.
When you reach the last word of the number string, add whatever you have in your working value to your running total.
Your running total is now the numeric representation of the number words you have just parsed. To make it a numeric ordinal again, simply call ToString on this number, then add "st" if the value of the ones place is '1', 'nd' if it's '2', 'rd' if it's '3', or 'th' if it's any other digit.
In English, the only numbers with special terms are 1-20 and the 10's multiples to 90 (20, 30, 40, etc), e.g. "Fortieth" (especially vexing as it isn't "Fourtieth") or "Nineteenth".
If you parse for those special cases, everything else is usually expressed as a number < 100 a multiplier, an optional "and" before the last expression, and "th" after the whole phrase e.g. "((Four) (Hundred)) [and] (Fifty)(Six) [th]".
In my opinion easiest way is generate arrays (by using code for normal/non reverse conversion) for first and second digit, then search in that arrays.
After 100 you just need to add "one hundred, one thousand" etc.
Hint: read words from the end, in that direction:
<--------- <----------
one hundred twenty first
4 3 2 1