Skip to main content

How to Convert a Number to Words in a Batch Script

Converting a number (like 123) into its text representation ("one hundred twenty-three") is a complex logical challenge. It is not a common administrative task but serves as an excellent, advanced example of what is possible with batch scripting's string manipulation, array simulation, and subroutine capabilities.

This guide will break down the logic required to solve this problem. Since there is no native command for this, we will build a full solution from scratch using a series of subroutines. We will cover numbers from zero up to the thousands, demonstrating how to handle each part of the number systematically.

note

This is a demonstration of advanced batch scripting logic. For any practical application, this task is far more easily and reliably accomplished with a single line of code in a more powerful language like PowerShell.

The Core Challenge: A Logic Puzzle, Not a Command

The cmd.exe interpreter has no built-in function for this. We cannot simply type CONVERT 123 to Words. We must create the entire logic ourselves. This involves:

  • Creating "arrays" (simulated with variables) to store the names for digits, teens, and tens.
  • Using substring manipulation to isolate the hundreds, tens, and ones digits.
  • Using a series of subroutines to handle each part of the number and build the final string.

The Strategy: Breaking the Number Down

Our script will handle numbers up to 9999. The core idea is to process the number in chunks.

  1. Thousands: Isolate the thousands digit, convert it to a word, and add "thousand".
  2. Hundreds: Isolate the hundreds digit, convert it to a word, and add "hundred".
  3. Tens and Ones: Handle the last two digits using a special subroutine that can process numbers from 0 to 99, correctly handling the "teens" (11-19) and decades (20, 30, 40, etc.).

Example Script: A Full Number-to-Words Converter

This script is a complete, self-contained solution with all the necessary logic and subroutines.

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

CALL :InitNumberNames

CALL :NumberToWords 1234 Result
ECHO 1234 -> !Result!

CALL :NumberToWords 567 Result
ECHO 567 -> !Result!

CALL :NumberToWords 82 Result
ECHO 82 -> !Result!

CALL :NumberToWords 15 Result
ECHO 15 -> !Result!

CALL :NumberToWords 9 Result
ECHO 9 -> !Result!

GOTO :EOF


:NumberToWords <Number> <ReturnVar>
SET "Num=%1"
SET "Words="

REM Handle Thousands
IF %Num% GEQ 1000 (
SET /A "Th = Num / 1000"
CALL :Convert_1_9 !Th! Word
SET "Words=!Word! thousand"
SET /A "Num = Num %% 1000"
)

REM Handle Hundreds
IF %Num% GEQ 100 (
SET /A "Hn = Num / 100"
CALL :Convert_1_9 !Hn! Word
SET "Words=!Words! !Word! hundred"
SET /A "Num = Num %% 100"
)

REM Handle Tens and Ones (0-99)
IF %Num% GTR 0 (
CALL :Convert_0_99 !Num! Word
SET "Words=!Words! !Word!"
)

REM Clean up leading space
FOR /F "tokens=*" %%A IN ("!Words!") DO SET "Words=%%A"
ENDLOCAL & SET "%2=%Words%"
GOTO :EOF


:Convert_0_99 <Number> <ReturnVar>
SET "N=%1"
SET "Word="
IF %N% LSS 10 (
CALL :Convert_1_9 !N! Word
) ELSE IF %N% LSS 20 (
CALL :Convert_10_19 !N! Word
) ELSE (
SET /A "T = N / 10"
SET /A "O = N %% 10"
CALL :Convert_Tens !T! TWord
SET "Word=!TWord!"
IF !O! GTR 0 (
CALL :Convert_1_9 !O! OWord
SET "Word=!Word!-!OWord!"
)
)
ENDLOCAL & SET "%2=%Word%"
GOTO :EOF


:Convert_1_9 <N> <RetVar> ( ENDLOCAL & SET "%2=!numName_%1!" ) & GOTO :EOF
:Convert_10_19 <N> <RetVar> ( ENDLOCAL & SET "%2=!teenName_%1!" ) & GOTO :EOF
:Convert_Tens <N> <RetVar> ( ENDLOCAL & SET "%2=!tensName_%1!" ) & GOTO :EOF


:InitNumberNames
SET "numName_1=one" & SET "numName_2=two" & SET "numName_3=three"
SET "numName_4=four" & SET "numName_5=five" & SET "numName_6=six"
SET "numName_7=seven" & SET "numName_8=eight" & SET "numName_9=nine"

SET "teenName_10=ten" & SET "teenName_11=eleven" & SET "teenName_12=twelve"
SET "teenName_13=thirteen" & SET "teenName_14=fourteen" & SET "teenName_15=fifteen"
SET "teenName_16=sixteen" & SET "teenName_17=seventeen" & SET "teenName_18=eighteen"
SET "teenName_19=nineteen"

SET "tensName_2=twenty" & SET "tensName_3=thirty" & SET "tensName_4=forty"
SET "tensName_5=fifty" & SET "tensName_6=sixty" & SET "tensName_7=seventy"
SET "tensName_8=eighty" & SET "tensName_9=ninety"
GOTO :EOF

How the Script Works

  1. :InitNumberNames: This subroutine initializes our "arrays" by creating a series of variables like numName_1="one", tensName_2="twenty", etc. This only needs to be run once.
  2. :NumberToWords: This is the main function. It takes a number and a return variable name.
    • It checks for thousands, hundreds, and tens/ones, processing each chunk.
    • It uses integer division (/) and modulo (%%) to isolate the digits (e.g., 1234 / 1000 = 1).
    • For each chunk, it calls a helper subroutine to get the word for that chunk.
    • It builds the final string piece by piece.
  3. :Convert_0_99: This is the most complex logic. It handles the special cases for numbers less than 10, the "teens" (10-19), and numbers from 20-99 (which require joining a "tens" word with a "digit" word).
  4. Helper Subroutines: The single-line subroutines like :Convert_1_9 are fast lookups. They use indirect expansion (!numName_%1!) to get the correct word from the "array" we initialized.

Common Pitfalls and How to Solve Them

  • Performance: This script is an exercise in logic, but it is very slow due to the sheer number of SET, CALL, and IF commands being executed. It is not suitable for converting a large quantity of numbers.
  • Special Characters: The script uses DelayedExpansion, making it vulnerable to any input that contains !. The input should be validated as a number first.
  • Large Numbers: Extending this script to handle millions or billions would require significant additional logic for each three-digit chunk.

The Superior PowerShell Alternative

This entire, complex batch script can be replaced by a single line of PowerShell code by leveraging a pre-written and publicly available function.

@ECHO OFF
SET "Number=1234"
powershell -Command "Add-Type -TypeDefinition @'
public class Spell{
// ... (Paste the C# Number-to-Words function here) ...
}
'@; [Spell]::ToWords(%Number%)"
note

While this requires a more complex PowerShell command with an embedded C# function, it is infinitely more robust, faster, and more extensible than the pure batch method. For any real-world use, this is the correct approach.

Conclusion

Converting a number to words is a perfect example of pushing the limits of what batch scripting can do.

  • It is possible to solve with pure batch commands by creating a series of subroutines that handle each part of the number.
  • The solution relies heavily on DelayedExpansion, simulated arrays, and integer arithmetic (/ and %%).
  • While a fun logical exercise, the pure-batch method is too slow and complex for any practical application.
  • For any real-world need, this task should be delegated to a more powerful language like PowerShell.