Aim
To convert an integer in the range 0–999 into its English-words representation using lookup tables and quotient/remainder decomposition into hundreds, tens and ones.
Theory
Number-to-words is a table-driven algorithm. English numbering is irregular below twenty (eleven, twelve, thirteen...), so no formula can generate those words — the correct model is a lookup array ones[0..19]. From twenty upward the system becomes positional again, captured by a second table tens[2..9] plus reuse of the ones table for the unit digit. The program decomposes n as hundreds = n / 100 and rest = n % 100 — the same quotient/remainder pattern as the digit-extraction practicals, but read top-down instead of bottom-up. Three design points merit attention. (1) ConvertTwoDigits is a pure function — its output depends only on its input and it mutates no external state — which makes it independently testable. (2) The string arrays are re-created on each call here; hoisting them to static readonly fields at class scope would allocate them once per process — a worthwhile micro-optimisation observation for the record book. (3) The guard if (n < 0 || n > 999) performs explicit domain validation and returns a message; a production library would instead throw ArgumentOutOfRangeException so callers cannot confuse an error with a real conversion. Extension to thousands (or the Indian lakh/crore grouping) is a loop over three-digit groups reusing exactly these two tables.
Requirements
- .NET SDK 8.0+ or the RUN CODE button; commands:
dotnet new console,dotnet run.
Procedure
- Create the project:
dotnet new console -n NumWords,cd NumWords, paste the code. - Run
dotnet runwith the default 507. - Verify the tricky bands: 13 (irregular teens), 40 (spelled "Forty", not "Fourty"), 100 (round hundred), 999 (maximum) and 0 (special case).
Explanation of the Code
ConvertTwoDigits(int n): the branchif (n < 20) return ones[n];serves the irregular band straight from the table; otherwisetens[n / 10]selects the tens word and the ternary(n % 10 > 0 ? " " + ones[n % 10] : "")appends the unit word ONLY when non-zero — eliminating the trailing-space bug for round tens like 40.NumberToWords(int n): special-cases zero first ("Zero", since the tables map 0 to an empty string), then validates the supported range, then splits the value withn / 100andn % 100.- The composition line
result += (result == "" ? "" : " ") + ConvertTwoDigits(rest);inserts a separator space only when a hundreds part already exists — producing "Five Hundred Seven" for 507 but plain "Seven" for 7. Mainprints the mapping with$"{num} -> {NumberToWords(num)}".
Expected Output
507 -> Five Hundred Seven
With 999 → Nine Hundred Ninety Nine; with 0 → Zero; with 1500 → Range supported: 0 to 999.
🎯 Viva Questions
- Why a lookup table for 0–19? — English teens are irregular; no rule generates "Eleven" from digits.
- What makes
ConvertTwoDigitsa pure function? — Same input always gives the same output and no external state is mutated. - Why is index 1 of the
tensarray empty? — Values 10–19 never reach the tens table; then < 20branch consumes them first. - How does the code avoid double spaces for 500? — Ternaries append the unit word (and its space) only when the component is non-zero.
- Throwing vs returning an error string for out-of-range input? — Libraries should throw
ArgumentOutOfRangeException; returning text is acceptable only in a teaching demo. - How would you extend the design to 999,999? — Convert three-digit groups with the same helper and suffix scale words like "Thousand".