views:

143

answers:

2

Does anyone know of a method to convert words like "first", "tenth" and "one hundredth" to their numeric equivalent?

Samples: "first" -> 1, "second" -> 2, "tenth" -> 10, "hundredth" -> 100

Any algorithm will suffice but I'm writing this in C#.

EDIT

It ain't pretty and only works with one word at a time but it suits my purposes. Maybe someone can improve it but I'm out of time.

 public static int GetNumberFromOrdinalString(string inputString)
    {
        string[] ordinalNumberWords = { "", "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth", "fourteenth", "fifteenth", "sixteenth", "seventeenth", "eighteenth", "nineteenth", "twentieth" };
        string[] ordinalNumberWordsTens = { "", "tenth", "twentieth", "thirtieth", "fortieth", "fiftieth", "sixtieth", "seventieth", "eightieth", "ninetieth" };
        string[] ordinalNumberWordsExtended = {"hundredth", "thousandth", "millionth", "billionth" };

        if (inputString.IsNullOrEmpty() || inputString.Length < 5 || inputString.Contains(" ")) return 0;

        if (ordinalNumberWords.Contains(inputString) || ordinalNumberWordsTens.Contains(inputString))
        {
            var outputMultiplier = ordinalNumberWords.Contains(inputString) ? 1 : 10;
            var arrayToCheck = ordinalNumberWords.Contains(inputString) ? ordinalNumberWords : ordinalNumberWordsTens;

            // Use the loop counter to get our output integer.
            for (int x = 0; x < arrayToCheck.Count(); x++)
            {
                if (arrayToCheck[x] == inputString)
                {
                    return x * outputMultiplier;
                }
            }
        }

        // Check if the number is one of our extended numbers and return the appropriate value.
        if (ordinalNumberWordsExtended.Contains(inputString))
        {
            return inputString == ordinalNumberWordsExtended[0] ? 100 : inputString == ordinalNumberWordsExtended[1] ? 1000 : inputString == ordinalNumberWordsExtended[2] ? 1000000 : 1000000000;
        }

        return 0;
    }
+1  A: 

I've never given this much thought beyond I know the word "and" is supposed to be the transition from whole numbers to decimals. Like

One Hundred Ninety-Nine Dollars and Ten Cents

not

One Hundred and Ninety-Nine Dollars.

Anyways any potential solution would have to parse the input string, raise any exceptions or otherwise return the value.

But first you'd have to know "the rules" This seems to be very arbitrary and based on tradition but this gentleman seems as good a place as any to start:

Ask Dr. Math

Christopher Painter
If you make it a rule that "and" is only used in the transition to decimals then you'll have a whole heap of problems when you try to sell your software in the Old World! Here in the UK we generally say "one hundred AND one pounds AND nineteen pence", or even "two hundred and six days till my birthday" -- "one hundred one" sounds very American to us.
AAT
Yup, arbitrary and tradition base. Thanks for the great language btw. We only had to make a few changes to it. :-)
Christopher Painter
A: 

I think you might end up having to map strings to values up to the maximum range you expect and then parse the string in order and place values as such. Since there's very little regular naming convention across and within order of magnitude, I don't think there's an elegant or easy way to parse a word to get its numeric value. Luckily, depending on the format, you probably only have to map every order of magnitude. For example, if you only expect numbers 0-100 and they are inputted as "ninety-nine" then you only need to map 0-9, then 10-100 in steps of 10.

jlv