Task

Show how to spell out a number in English.

You can use a preexisting implementation or roll your own, but you should support inputs up to at least one million (or the maximum value of your language's default bounded integer type, if that's less).

Support for inputs other than positive integers (like zero, negative integers, and floating-point numbers) is optional.



Related task

   Spelling of ordinal numbers.


100H:
BDOS: PROCEDURE (FN, ARG); DECLARE FN BYTE, ARG ADDRESS; GO TO 5; END BDOS;
EXIT: PROCEDURE; CALL BDOS(0,0); END EXIT;
PRINT: PROCEDURE (S); DECLARE S ADDRESS; CALL BDOS(9,S); END PRINT;
 
DECLARE FCB$NAME LITERALLY '5DH'; /* CP/M STORES COMMAND ARGUMENT HERE */
 
/* READ ASCII NUMBER */
READ$NUMBER: PROCEDURE (PTR) ADDRESS;
    DECLARE PTR ADDRESS, C BASED PTR BYTE, RSLT ADDRESS;
    RSLT = 0;
    DO WHILE '0' <= C AND C <= '9';
        RSLT = RSLT * 10 + C - '0';
        PTR = PTR + 1;
    END;
    RETURN RSLT;
END;
 
/* SPELL 16-BIT NUMBER */
SPELL: PROCEDURE (N);
    DECLARE N ADDRESS;
    IF N=0 THEN DO;
        CALL PRINT(.'ZERO$');
        RETURN;
    END;
    SMALL: PROCEDURE (N) ADDRESS;
        DECLARE N BYTE;
        DO CASE N;
            RETURN .'$';         RETURN .'ONE$';      RETURN .'TWO$';
            RETURN .'THREE$';    RETURN .'FOUR$';     RETURN .'FIVE$';
            RETURN .'SIX$';      RETURN .'SEVEN$';    RETURN .'EIGHT$';
            RETURN .'NINE$';     RETURN .'TEN$';      RETURN .'ELEVEN$';
            RETURN .'TWELVE$';   RETURN .'THIRTEEN$'; RETURN .'FOURTEEN$';
            RETURN .'FIFTEEN$';  RETURN .'SIXTEEN$';  RETURN .'SEVENTEEN$';
            RETURN .'EIGHTEEN$'; RETURN .'NINETEEN$';
        END;
    END SMALL;
    TEENS: PROCEDURE (N) ADDRESS;
        DECLARE N BYTE;
        DO CASE N-2;
            RETURN .'TWENTY$';
            RETURN .'THIRTY$';
            RETURN .'FORTY$';
            RETURN .'FIFTY$';
            RETURN .'SIXTY$';
            RETURN .'SEVENTY$';
            RETURN .'EIGHTY$';
            RETURN .'NINETY$';
        END;
    END TEENS;
    LESS$100: PROCEDURE (N);
        DECLARE N BYTE;
        IF N >= 20 THEN DO;
            CALL PRINT(TEENS(N/10));
            N = N MOD 10;
            IF N > 0 THEN CALL PRINT(.'-$');
        END;
        CALL PRINT(SMALL(N));
    END LESS$100;
    LESS$1000: PROCEDURE (N);
        DECLARE N ADDRESS;
        IF N >= 100 THEN DO;
            CALL LESS$100(N/100);
            CALL PRINT(.' HUNDRED$');
            N = N MOD 100;
            IF N > 0 THEN CALL PRINT(.' $');
        END;
        CALL LESS$100(N);
    END LESS$1000;
    IF N >= 1000 THEN DO;
        CALL LESS$1000(N/1000);
        CALL PRINT(.' THOUSAND$');
        N = N MOD 1000;
        IF N > 0 THEN CALL PRINT(.' $');
    END;
    CALL LESS$1000(N);
END SPELL;
 
CALL SPELL(READ$NUMBER(FCB$NAME));
CALL EXIT;
EOF