Names to numbers

Revision as of 07:46, 20 November 2021 by Alextretyak (talk | contribs) (Added 11l)

Translate the spelled-out English name of a number to a number. 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).

Names to numbers is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

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

See also

11l

Translation of: Nim

<lang 11l>V Names = [‘one’ = Int64(1),

          ‘two’ = 2,
          ‘three’ = 3,
          ‘four’ = 4,
          ‘five’ = 5,
          ‘six’ = 6,
          ‘seven’ = 7,
          ‘eight’ = 8,
          ‘nine’ = 9,
          ‘ten’ = 10,
          ‘eleven’ = 11,
          ‘twelve’ = 12,
          ‘thirteen’ = 13,
          ‘fourteen’ = 14,
          ‘fifteen’ = 15,
          ‘sixteen’ = 16,
          ‘seventeen’ = 17,
          ‘eighteen’ = 18,
          ‘nineteen’ = 19,
          ‘twenty’ = 20,
          ‘thirty’ = 30,
          ‘forty’ = 40,
          ‘fifty’ = 50,
          ‘sixty’ = 60,
          ‘seventy’ = 70,
          ‘eighty’ = 80,
          ‘ninety’ = 90,
          ‘hundred’ = 100,
          ‘thousand’ = 1000,
          ‘million’ = 1000000,
          ‘billion’ = 1000000000,
          ‘trillion’ = 1000000000000,
          ‘quadrillion’ = 1000000000000000,
          ‘quintillion’ = 1000000000000000000]

V Zeros = [‘zero’, ‘nought’, ‘nil’, ‘none’, ‘nothing’]

F nameToNum(name)

  V text = name.lowercase()
  V isNegative = text.starts_with(‘minus ’)
  I isNegative
     text = text[6..]
  I text.starts_with(‘a’)
     text = ‘one’text[1..]
  V words = text.split(re:‘,|-| and | ’).filter(w -> !w.empty)
  I words.len == 1 & words[0] C Zeros
     R Int64(0)
  V multiplier = Int64(1)
  V sum = Int64(0)
  L(i) (words.len - 1 .< -1).step(-1)
     V num = Names.get(words[i], 0)
     I num >= 1000
        multiplier = num
        I i == 0
           sum += multiplier
     E I num >= 100
        multiplier *= 100
        I i == 0
           sum += multiplier
     E
        sum += num * multiplier
  R I isNegative {-sum} E sum

V names = [

  ‘none’,
  ‘one’,
  ‘twenty-five’,
  ‘minus one hundred and seventeen’,
  ‘hundred and fifty-six’,
  ‘minus two thousand two’,
  ‘nine thousand, seven hundred, one’,
  ‘minus six hundred and twenty six thousand, eight hundred and fourteen’,
  ‘four million, seven hundred thousand, three hundred and eighty-six’,
  ‘fifty-one billion, two hundred and fifty-two million, seventeen thousand, one hundred eighty-four’,
  ‘two hundred and one billion, twenty-one million, two thousand and one’,
  ‘minus three hundred trillion, nine million, four hundred and one thousand and thirty-one’,
  ‘seventeen quadrillion, one hundred thirty-seven’,
  ‘a quintillion, eight trillion and five’,
  ‘minus nine quintillion, two hundred and twenty-three quadrillion, three hundred and seventy-two trillion, thirty-six billion, eight hundred and fifty-four million, seven hundred and seventy-five thousand, eight hundred and eight’]

L(name) names

  print(‘#20’.format(nameToNum(name))‘ = ’name)</lang>
Output:
                   0 = none
                   1 = one
                  25 = twenty-five
                -117 = minus one hundred and seventeen
                 156 = hundred and fifty-six
               -2002 = minus two thousand two
                9701 = nine thousand, seven hundred, one
             -626814 = minus six hundred and twenty six thousand, eight hundred and fourteen
             4700386 = four million, seven hundred thousand, three hundred and eighty-six
         51252017184 = fifty-one billion, two hundred and fifty-two million, seventeen thousand, one hundred eighty-four
        201021002001 = two hundred and one billion, twenty-one million, two thousand and one
    -300000009401031 = minus three hundred trillion, nine million, four hundred and one thousand and thirty-one
   17000000000000137 = seventeen quadrillion, one hundred thirty-seven
 1000008000000000005 = a quintillion, eight trillion and five
-9223372036854775808 = minus nine quintillion, two hundred and twenty-three quadrillion, three hundred and seventy-two trillion, thirty-six billion, eight hundred and fifty-four million, seven hundred and seventy-five thousand, eight hundred and eight

Common Lisp

A counterpart to (format t "~R" ...). <lang Lisp>(defpackage number-names

 (:use cl))

(in-package number-names)

(defparameter *ones*

 '((one   . 1)
   (two   . 2)
   (three . 3)
   (four  . 4)
   (five  . 5)
   (six   . 6)
   (seven . 7)
   (eight . 8)
   (nine  . 9)))

(defparameter *teens*

 '((ten       . 10)
   (eleven    . 11)
   (twelve    . 12)
   (thirteen  . 13)
   (fourteen  . 14)
   (fifteen   . 15)
   (sixteen   . 16)
   (seventeen . 17)
   (eighteen  . 18)
   (nineteen  . 19)))

(defparameter *tens*

 '((twenty  . 20)
   (thirty  . 30)
   (forty   . 40)
   (fifty   . 50)
   (sixty   . 60)
   (seventy . 70)
   (eighty  . 80)
   (ninety  . 90)))

(defparameter *hundred*

 '((hundred . 100)))

(defparameter *illions*

 '((quintillion . 1000000000000000000)
   (quadrillion . 1000000000000000)
   (trillion    . 1000000000000)
   (billion     . 1000000000)
   (million     . 1000000)
   (thousand    . 1000)))

(defparameter *delims* '(#\Space #\Tab #\Newline #\-))

Turn a single delimited word into an atom.

(defun tokenize-word (word)

 (let ((stream (make-string-output-stream)))
   (loop do
        (let ((char (pop word)))
          (cond ((null char) (return))
                ((member char *delims*) (return))
                (t (write-char char stream)))))
   (let ((out (get-output-stream-string stream)))
     (values (intern (string-upcase out) 'number-names)
             word))))
Tokenize the input string.

(defun tokenize (word)

 (let ((word (coerce word 'list))
       (tokens (list)))
   (loop do
        (let ((char (pop word)))
          (cond ((null char) (return))
                ((member char *delims*) nil)
                (t (multiple-value-bind (token rest-word)
                       (tokenize-word (push char word))
                     (setf word rest-word)
                     (push token tokens))))))
   (reverse tokens)))
Define a state machine to parse a subsection of a number
that precedes an -illion.

(defmacro defstate (name end-transitions-p &rest transitions)

 (let ((token (gensym "TOKEN"))
       (number (gensym "NUMBER"))
       (illions (gensym "ILLIONS"))
       (illion (gensym "ILLION")))
 `(defun ,name (,token ,number ,illions)
    ,(append '(cond)
             (loop for trans in transitions collect
                  (destructuring-bind (place to-state op) trans
                    `((assoc ,token ,place)
                      (values ',to-state
                              (,op ,number (cdr (assoc ,token ,place)))))))
             (when end-transitions-p
               `(((assoc ,token ,illions)
                  (throw 'done
                    (let ((,illion (assoc ,token ,illions)))
                      (values (* ,number (cdr ,illion)) (car ,illion)))))
                 ((null ,token) (throw 'done (values ,number nil)))))
             `((t (error "Unexpected token ~a" ,token)))))))

(defstate state-a nil

 (*ones* state-b +)
 (*tens* state-d +)
 (*teens* state-e +))

(defstate state-b t

 (*hundred* state-c *))

(defstate state-c t

 (*ones* state-e +)
 (*tens* state-d +)
 (*teens* state-e +))

(defstate state-d t

 (*ones* state-e +))

(defstate state-e t)

(defun consume-illions (illion illions)

 (cond ((null illions) nil)
       ((eq illion (caar illions)) (cdr illions))
       (t (consume-illions illion (cdr illions)))))
Parse a number up to the next -illion.
Errors on numbers that (format t "~R" ..)
would not generate, like "one thousand one million".

(defun parse-sub-number (tokens illions)

 (let ((number 0)
       (state 'state-a))
   (multiple-value-bind (number illion)
       (catch 'done
         (loop do
              (let ((token (pop tokens)))
                (multiple-value-bind (next-state next-number)
                    (funcall state token number illions)
                  (setf state next-state)
                  (setf number next-number)))))
     (values number
             (if illion
                 (consume-illions illion illions)
                 illions)
             tokens))))
Parse the list of tokenized number parts.

(defun parse-number (tokens)

 (let ((illions *illions*)
       (total 0)
       (negative-p (eq (car tokens) 'negative)))
   (when negative-p (pop tokens))
   (if (eq (car tokens) 'zero)
       (if (null (cdr tokens))
           0
           (error "Unexpected token ~a" (cadr tokens)))
       (loop do
            (multiple-value-bind (number new-illions rest-tokens)
                (parse-sub-number tokens illions)
              (setf illions new-illions)
              (incf total number)
              (setf tokens rest-tokens)
              (unless tokens (return (* (if negative-p -1 1) total))))))))

(defun parse (word)

 (parse-number (tokenize word)))

(defun test ()

 (let ((test-numbers
        '(+0
          -3
          +5
          -7
          +11
          -13
          +17
          -19
          +23
          -29
          201021002001
          -20102100201
          2010210020
          -201021002
          20102100
          -2010210
          201021
          -20103
          2010
          -201
          20
          -2
          0)))
   (princ "number => (format t \"~R\" number) => (parse (format t \"~R\" number))")
   (terpri)
   (mapc (lambda (number)
           (let ((word (format nil "~R" number)))
             (format t "~a => ~a => ~a~%" number word (parse word))))
         test-numbers))
 (values))</lang>

Running the test procedure: <lang none>CL-USER> (number-names::test) number => (format t "~R" number) => (parse (format t "~R" number)) 0 => zero => 0 -3 => negative three => -3 5 => five => 5 -7 => negative seven => -7 11 => eleven => 11 -13 => negative thirteen => -13 17 => seventeen => 17 -19 => negative nineteen => -19 23 => twenty-three => 23 -29 => negative twenty-nine => -29 201021002001 => two hundred one billion twenty-one million two thousand one => 201021002001 -20102100201 => negative twenty billion one hundred two million one hundred thousand two hundred one => -20102100201 2010210020 => two billion ten million two hundred ten thousand twenty => 2010210020 -201021002 => negative two hundred one million twenty-one thousand two => -201021002 20102100 => twenty million one hundred two thousand one hundred => 20102100 -2010210 => negative two million ten thousand two hundred ten => -2010210 201021 => two hundred one thousand twenty-one => 201021 -20103 => negative twenty thousand one hundred three => -20103 2010 => two thousand ten => 2010 -201 => negative two hundred one => -201 20 => twenty => 20 -2 => negative two => -2 0 => zero => 0

No value</lang>

D

This uses the D module from the Number names task.

Translation of: Python

<lang d>import std.stdio, std.array, std.string, std.algorithm, std.bigint,

      std.range, number_names;

BigInt bigIntFromWords(in string num) in {

   assert(!num.empty);

} body {

   auto words = num.replace(",", "").replace(" and ", " ")
                .replace("-", " ").split;
   immutable sign = (words[0] == "minus") ? -1 : +1;
   if (sign == -1)
       words = words[1 .. $];
   BigInt bsmall, total;
   foreach (const word; words) {
       if (small.canFind(word)) {
           bsmall += small.countUntil(word);
       } else if (tens.canFind(word)) {
           bsmall += tens.countUntil(word) * 10;
       } else if (word == "hundred") {
           bsmall *= 100;
       } else if (word == "thousand") {
           total += bsmall * 1000;
           bsmall = 0;
       } else if (huge.canFind(word)) {
           total += bsmall * BigInt(1000) ^^ huge.countUntil(word);
           bsmall = 0;
       } else {
           immutable msg = format("Don't understand %s part of %s",
                                  word, num);
           throw new Exception(msg);
       }
   }
   return sign * (total + bsmall);

}

void main() {

   foreach (immutable n; iota(-10000, 10000, 17))
       assert(n == n.BigInt.spellBigInt.bigIntFromWords);
   foreach (immutable p; 0 .. 20) {
       auto n = 13.BigInt ^^ p;
       assert(n == n.spellBigInt.bigIntFromWords);
   }
   writeln("This shows <==> for a successful round trip, " ~
           " <??> otherwise:");
   foreach (immutable n; [0, -3, 5, -7, 11, -13, 17, -19, 23, -29]) {
       const txt = n.BigInt.spellBigInt;
       auto num = txt.bigIntFromWords;
       writefln("%+4d <%s> %s", n, (n == num) ? "==" : "??", txt);
   }
   writeln;
   long n = 201_021_002_001;
   while (n) {
       const txt = n.BigInt.spellBigInt;
       auto num = txt.bigIntFromWords;
       writefln("%12d <%s> %s", n, (n == num) ? "==" : "??", txt);
       n /= -10;
   }
   const txt = n.BigInt.spellBigInt;
   auto num = txt.bigIntFromWords;
   writefln("%12d <%s> %s", n, (n == num) ? "==" : "??", txt);

}</lang>

Output:
This shows <==> for a successful round trip,  <??> otherwise:
  +0 <==> zero
  -3 <==> minus three
  +5 <==> five
  -7 <==> minus seven
 +11 <==> eleven
 -13 <==> minus thirteen
 +17 <==> seventeen
 -19 <==> minus nineteen
 +23 <==> twenty-three
 -29 <==> minus twenty-nine

201021002001 <==> two hundred and one billion, twenty-one million, two thousand, and one
-20102100200 <==> minus twenty billion, one hundred and two million, one hundred thousand, and two hundred
  2010210020 <==> two billion, ten million, two hundred and ten thousand, and twenty
  -201021002 <==> minus two hundred and one million, twenty-one thousand, and two
    20102100 <==> twenty million, one hundred and two thousand, and one hundred
    -2010210 <==> minus two million, ten thousand, two hundred and ten
      201021 <==> two hundred and one thousand, and twenty-one
      -20102 <==> minus twenty thousand, one hundred and two
        2010 <==> two thousand, and ten
        -201 <==> minus two hundred and one
          20 <==> twenty
          -2 <==> minus two
           0 <==> zero

Delphi

Library: System.Math
Translation of: Kotlin

<lang Delphi> program Names_to_numbers;

{$APPTYPE CONSOLE}

uses

 System.SysUtils,
 System.Generics.Collections,
 System.Math;

function CreateMap: TDictionary<string, Int64>; const

 smallies: array[1..19] of string = ('one', 'two', 'three', 'four', 'five',
   'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen',
   'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen');
 tens: array[2..9] of string = ('twenty', 'thirty', 'forty', 'fifty', 'sixty',
   'seventy', 'eighty', 'ninety');
 maxies: array[1..6] of string = ('thousand', 'million', 'billion', 'trillion',
   'quadrillion', 'quintillion');

var

 i: Integer;

begin

 Result := TDictionary<string, Int64>.Create();
 for i := 1 to 19 do
   Result.Add(smallies[i], i);
 for i := 2 to 9 do
   Result.Add(tens[i], i * 10);
 for i := 1 to 6 do
   Result.Add(maxies[i], Trunc(IntPower(10, i * 3)));
 Result.Add('hundred', 100);

end;

const

 zeros = '"zero","nought","nil","none","nothing"';
 MIN_INT64 = -9223372036854775808;

var

 Names: TDictionary<string, Int64>;

function nameToNum(name: string): Int64; var

 Text, w: string;
 IsNegative: Boolean;
 words: TArray<string>;
 size: integer;
 multiplier, lastNum, sum, num: Int64;
 i: Integer;

begin

 Text := name.trim().ToLower();
 IsNegative := Text.startsWith('minus ');
 if (IsNegative) then
   Text := Text.Substring(6);
 if (Text.startsWith('a ')) then
   Text := 'one' + Text.Substring(1);
 words := Text.split([',', '-', ' and ', ' ']);
 size := Length(words);
 if ((size = 1) and (zeros.indexOf(words[0].QuotedString('"')) > -1)) then
   exit(0);
 multiplier := 1;
 lastNum := 0;
 sum := 0;
 for i := size - 1 downto 0 do
 begin
   w := words[i];
   if w.Trim.IsEmpty then
     Continue;
   if not Names.ContainsKey(w) then
     raise EArgumentException.Create(w + ' is not a valid number');
   num := Names[w];
   if (num = lastNum) then
     raise EArgumentException.Create(name + ' is not a well formed numeric string')
   else if (num >= 1000) then
   begin
     if (lastNum >= 100) then
       raise EArgumentException.Create(name + ' is not a well formed numeric string');
     multiplier := num;
     if (i = 0) then
       sum := sum + multiplier;
   end
   else if (num >= 100) then
   begin
     multiplier := multiplier * 100;
     if (i = 0) then
       sum := sum + multiplier
   end
   else if (num >= 20) then
   begin
     if (lastNum >= 10) and (lastNum <= 90) then
       raise EArgumentException.Create(name + ' is not a well formed numeric string');
     sum := sum + num * multiplier;
   end
   else
   begin
     if (lastNum >= 1) and (lastNum <= 90) then
       raise EArgumentException.Create(name + ' is not a well formed numeric string');
     sum := sum + num * multiplier;
   end;
   lastNum := num;
 end;
 if (IsNegative and (sum = -sum)) then
   exit(MIN_INT64)
 else if (sum < 0) then
   raise EArgumentException.Create(name + ' is outside the range of a Long integer');
 if (IsNegative) then
   Result := -sum
 else
   result := sum;

end;

const

 TestCases: array[0..14] of string = ('none', 'one', 'twenty-five',
   'minus one hundred and seventeen', 'hundred and fifty-six',
   'minus two thousand two', 'nine thousand, seven hundred, one',
   'minus six hundred and twenty six thousand, eight hundred and fourteen',
   'four million, seven hundred thousand, three hundred and eighty-six',
   'fifty-one billion, two hundred and fifty-two million, seventeen thousand, one hundred eighty-four',
   'two hundred and one billion, twenty-one million, two thousand and one',
   'minus three hundred trillion, nine million, four hundred and one thousand and thirty-one',
   'seventeen quadrillion, one hundred thirty-seven',
   'a quintillion, eight trillion and five',
   'minus nine quintillion, two hundred and twenty-three quadrillion, three hundred and seventy-two trillion, thirty-six billion, eight hundred and fifty-four million, seven hundred and seventy-five thousand, eight hundred and eight');

var

 name: string;

begin

 Names := CreateMap;
 for name in TestCases do
   Writeln(nameToNum(name): 20, ' = ', name);
 Names.free;
 Readln;

end.</lang>

Output:
                   0 = none
                   1 = one
                  25 = twenty-five
                -117 = minus one hundred and seventeen
                 156 = hundred and fifty-six
               -2002 = minus two thousand two
                9701 = nine thousand, seven hundred, one
             -626814 = minus six hundred and twenty six thousand, eight hundred and fourteen
             4700386 = four million, seven hundred thousand, three hundred and eighty-six
         51252017184 = fifty-one billion, two hundred and fifty-two million, seventeen thousand, one hundred eighty-four
        201021002001 = two hundred and one billion, twenty-one million, two thousand and one
    -300000009401031 = minus three hundred trillion, nine million, four hundred and one thousand and thirty-one
   17000000000000137 = seventeen quadrillion, one hundred thirty-seven
 1000008000000000005 = a quintillion, eight trillion and five
-9223372036854775808 = minus nine quintillion, two hundred and twenty-three quadrillion, three hundred and seventy-two trillion, thirty-six billion, eight hundred and fifty-four million, seven hundred and seventy-five thousand, eight hundred and eight

Factor

This solution parses number names in the same format that Factor's existing number>text word outputs. Meaning that for numbers under 10^66, number>text and text>number ought to be inverses of each other. <lang factor>USING: arrays formatting grouping kernel math math.functions math.parser multiline peg peg.ebnf sequences sequences.deep ;

! Make sure a number is monotonically decreasing. ! So "one hundred and three" is valid but ! "three and one hundred" is not.

check-natural ( seq -- )
   [ > ] monotonic? [ "Invalid number." throw ] unless ;


! Parse number names with Factor's EBNF-like DSL.

EBNF: text>number [=[

 one       = "one"~       => 1 
 two       = "two"~       => 2 
 three     = "three"~     => 3 
 four      = "four"~      => 4 
 five      = "five"~      => 5 
 six       = "six"~       => 6 
 seven     = "seven"~     => 7 
 eight     = "eight"~     => 8 
 nine      = "nine"~      => 9 
 ten       = "ten"~       => 10 
 eleven    = "eleven"~    => 11 
 twelve    = "twelve"~    => 12 
 thirteen  = "thirteen"~  => 13 
 fourteen  = "fourteen"~  => 14 
 fifteen   = "fifteen"~   => 15 
 sixteen   = "sixteen"~   => 16 
 seventeen = "seventeen"~ => 17 
 eighteen  = "eighteen"~  => 18 
 nineteen  = "nineteen"~  => 19 
 twenty    = "twenty"~    => 20 
 thirty    = "thirty"~    => 30 
 forty     = "forty"~     => 40 
 fifty     = "fifty"~     => 50 
 sixty     = "sixty"~     => 60 
 seventy   = "seventy"~   => 70 
 eighty    = "eighty"~    => 80 
 ninety    = "ninety"~    => 90 
 hundred   = "hundred"~   => 100 
 thousand  = "thousand"~  => 1000 
 million   = "million"~   => 6 10^ 
 billion   = "billion"~   => 9 10^ 
 trillion  = "trillion"~  => 12 10^ 
 quadrillion = "quadrillion"~ => 15 10^ 
 quintillion = "quintillion"~ => 18 10^ 
 sextillion  = "sextillion"~  => 21 10^ 
 septillion  = "septillion"~  => 24 10^ 
 octillion   = "octillion"~   => 27 10^ 
 nonillion   = "nonillion"~   => 30 10^ 
 decillion   = "decillion"~   => 33 10^ 
 undecillion = "undecillion"~ => 36 10^ 
 duodecillion      = "duodecillion"~      => 39 10^ 
 tredecillion      = "tredecillion"~      => 42 10^ 
 quattuordecillion = "quattuordecillion"~ => 45 10^ 
 quindecillion     = "quindecillion"~     => 48 10^ 
 sexdecillion      = "sexdecillion"~      => 51 10^ 
 septendecillion   = "septendecillion"~   => 54 10^ 
 octodecillion     = "octodecillion"~     => 57 10^ 
 novemdecillion    = "novemdecillion"~    => 60 10^ 
 vigintillion      = "vigintillion"~      => 63 10^ 
 name      = vigintillion|novemdecillion|octodecillion|
             septendecillion|sexdecillion|quindecillion|
             quattuordecillion|tredecillion|duodecillion|
             undecillion|decillion|nonillion|octillion|
             septillion|sextillion|quintillion|quadrillion|
             trillion|billion|million|thousand|hundred|ninety|
             eighty|seventy|sixty|fifty|forty|thirty|twenty|
             nineteen|eighteen|seventeen|sixteen|fifteen|
             fourteen|thirteen|twelve|eleven|ten|nine|eight|
             seven|six|five|four|three|two|one
 ws        = [\n\t\r ]* => drop ignore 
 dual      = name "-"~ name => sum 
 atom      = dual|name
 atoms     = (ws atom ws)+ => product 
 compound  = atoms "and"~ ws atom ws name ws
           => [[ first3 swap over [ * ] 2bi@ 2array ]]
 simple    = atoms "and"~ ws atom ws
 basic     = "and"~ ws atom ws
 group     = compound|simple|basic|atoms
 natural   = (group (","~)? )+
           => flatten dup check-natural sum 
 
 negative  = "negative"~ ws natural => -1 * 
 zero      = "zero"~ => 0 
 integer   = zero|negative|natural
 fraction  = integer "divided by"~ natural => first2 / 
 digit     = nine|eight|seven|six|five|four|three|two|one|zero
 mantissa  = (ws digit ws)+
           => [[ [ number>string ] map concat ]]
 decimal   = integer ws "point"~ mantissa
           => [[ first2 [ number>string ] dip "." glue string>number ]]
 number    = fraction|decimal|integer

]=]


names-to-numbers-demo ( -- )
   {
       "zero"
       "one"
       "negative one"
       "nine"
       "ten"
       "negative seventeen"
       "twenty-seven"
       "one hundred"
       "one hundred and one"
       "negative one hundred and nineteen"
       "four hundred and ninety-five thousand, three hundred and thirty-three"
       "two hundred million"
       "two hundred million and twenty-two"
       "two hundred million, two thousand and two"
       "one trillion, one billion, one million, one thousand and one"
       "four hundred and fifty-three vigintillion"
       "zero point one"
       "one point one"
       "negative one thousand, three hundred point zero zero five six seven"
       "thirty-seven divided by ninety-one"
       "zero divided by two nonillion"
       "negative one divided by two nonillion"
   }
   [ dup text>number "%s => %u\n" printf ] each ;

names-to-numbers-demo</lang>

Output:
zero => 0
one => 1
negative one => -1
nine => 9
ten => 10
negative seventeen => -17
twenty-seven => 27
one hundred => 100
one hundred and one => 101
negative one hundred and nineteen => -119
four hundred and ninety-five thousand, three hundred and thirty-three => 495333
two hundred million => 200000000
two hundred million and twenty-two => 200000022
two hundred million, two thousand and two => 200002002
one trillion, one billion, one million, one thousand and one => 1001001001001
four hundred and fifty-three vigintillion => 453000000000000000000000000000000000000000000000000000000000000000
zero point one => 0.1
one point one => 1.1
negative one thousand, three hundred point zero zero five six seven => -1300.00567
thirty-seven divided by ninety-one => 37/91
zero divided by two nonillion => 0
negative one divided by two nonillion => -1/2000000000000000000000000000000

Go

Translation of: Kotlin

<lang go>package main

import (

   "fmt"
   "math"
   "regexp"
   "strings"

)

var names = map[string]int64{

   "one":         1,
   "two":         2,
   "three":       3,
   "four":        4,
   "five":        5,
   "six":         6,
   "seven":       7,
   "eight":       8,
   "nine":        9,
   "ten":         10,
   "eleven":      11,
   "twelve":      12,
   "thirteen":    13,
   "fourteen":    14,
   "fifteen":     15,
   "sixteen":     16,
   "seventeen":   17,
   "eighteen":    18,
   "nineteen":    19,
   "twenty":      20,
   "thirty":      30,
   "forty":       40,
   "fifty":       50,
   "sixty":       60,
   "seventy":     70,
   "eighty":      80,
   "ninety":      90,
   "hundred":     100,
   "thousand":    1000,
   "million":     1000000,
   "billion":     1000000000,
   "trillion":    1000000000000,
   "quadrillion": 1000000000000000,
   "quintillion": 1000000000000000000,

}

var seps = regexp.MustCompile(`,|-| and | `) var zeros = regexp.MustCompile(`^(zero|nought|nil|none|nothing)$`)

func nameToNum(name string) (int64, error) {

   text := strings.ToLower(strings.TrimSpace(name))
   isNegative := strings.HasPrefix(text, "minus ")
   if isNegative {
       text = text[6:]
   }
   if strings.HasPrefix(text, "a ") {
       text = "one" + text[1:]
   }
   words := seps.Split(text, -1)
   for i := len(words) - 1; i >= 0; i-- {
       if words[i] == "" {
           if i < len(words)-1 {
               copy(words[i:], words[i+1:])
           }
           words = words[:len(words)-1]
       }
   }
   size := len(words)
   if size == 1 && zeros.MatchString(words[0]) {
       return 0, nil
   }
   var multiplier, lastNum, sum int64 = 1, 0, 0
   for i := size - 1; i >= 0; i-- {
       num, ok := names[words[i]]
       if !ok {
           return 0, fmt.Errorf("'%s' is not a valid number", words[i])
       } else {
           switch {
           case num == lastNum, num >= 1000 && lastNum >= 100:
               return 0, fmt.Errorf("'%s' is not a well formed numeric string", name)
           case num >= 1000:
               multiplier = num
               if i == 0 {
                   sum += multiplier
               }
           case num >= 100:
               multiplier *= 100
               if i == 0 {
                   sum += multiplier
               }
           case num >= 20 && lastNum >= 10 && lastNum <= 90:
               return 0, fmt.Errorf("'%s' is not a well formed numeric string", name)
           case num >= 20:
               sum += num * multiplier
           case lastNum >= 1 && lastNum <= 90:
               return 0, fmt.Errorf("'%s' is not a well formed numeric string", name)
           default:
               sum += num * multiplier
           }
       }
       lastNum = num
   }
   if isNegative && sum == -sum {
       return math.MinInt64, nil
   }
   if sum < 0 {
       return 0, fmt.Errorf("'%s' is outside the range of an int64", name)
   }
   if isNegative {
       return -sum, nil
   } else {
       return sum, nil
   }

}

func main() {

   names := [...]string{
       "none",
       "one",
       "twenty-five",
       "minus one hundred and seventeen",
       "hundred and fifty-six",
       "minus two thousand two",
       "nine thousand, seven hundred, one",
       "minus six hundred and twenty six thousand, eight hundred and fourteen",
       "four million, seven hundred thousand, three hundred and eighty-six",
       "fifty-one billion, two hundred and fifty-two million, seventeen thousand, one hundred eighty-four",
       "two hundred and one billion, twenty-one million, two thousand and one",
       "minus three hundred trillion, nine million, four hundred and one thousand and thirty-one",
       "seventeen quadrillion, one hundred thirty-seven",
       "a quintillion, eight trillion and five",
       "minus nine quintillion, two hundred and twenty-three quadrillion, three hundred and seventy-two trillion, thirty-six billion, eight hundred and fifty-four million, seven hundred and seventy-five thousand, eight hundred and eight",
   }
   for _, name := range names {
       num, err := nameToNum(name)
       if err != nil {
           fmt.Println(err)
       } else {
           fmt.Printf("%20d = %s\n", num, name)
       }
   }

}</lang>

Output:
                   0 = none
                   1 = one
                  25 = twenty-five
                -117 = minus one hundred and seventeen
                 156 = hundred and fifty-six
               -2002 = minus two thousand two
                9701 = nine thousand, seven hundred, one
             -626814 = minus six hundred and twenty six thousand, eight hundred and fourteen
             4700386 = four million, seven hundred thousand, three hundred and eighty-six
         51252017184 = fifty-one billion, two hundred and fifty-two million, seventeen thousand, one hundred eighty-four
        201021002001 = two hundred and one billion, twenty-one million, two thousand and one
    -300000009401031 = minus three hundred trillion, nine million, four hundred and one thousand and thirty-one
   17000000000000137 = seventeen quadrillion, one hundred thirty-seven
 1000008000000000005 = a quintillion, eight trillion and five
-9223372036854775808 = minus nine quintillion, two hundred and twenty-three quadrillion, three hundred and seventy-two trillion, thirty-six billion, eight hundred and fifty-four million, seven hundred and seventy-five thousand, eight hundred and eight

Haskell

Translation of: Common Lisp

<lang Haskell>import Data.Char (toLower)

type Symbol = (String, Integer) type BinOp = (Integer -> Integer -> Integer) type State = [Transition]

data Transition = Transition [Symbol] State BinOp

               | Illion State BinOp
               | Done

type Words = [String] type Accumulator = Integer type TapeValue = (Accumulator, [Symbol], Words)

ones, teens, tens, hundred, illions :: [Symbol] ones =

   [("one", 1)
   ,("two", 2)
   ,("three", 3)
   ,("four", 4)
   ,("five", 5)
   ,("six", 6)
   ,("seven", 7)
   ,("eight", 8)
   ,("nine", 9)]

teens =

   [("ten", 10)
   ,("eleven", 11)
   ,("twelve", 12)
   ,("thirteen", 13)
   ,("fourteen", 14)
   ,("fifteen", 15)
   ,("sixteen", 16)
   ,("seventeen", 17)
   ,("eighteen", 18)
   ,("nineteen", 19)]

tens =

   [("twenty", 20)
   ,("thirty", 30)
   ,("forty", 40)
   ,("fifty", 50)
   ,("sixty", 60)
   ,("seventy", 70)
   ,("eighty", 80)
   ,("ninety", 90)]

hundred =

   [("hundred", 100)]

illions =

   [("quintillion", 10 ^ 18)
   ,("quadrillion", 10 ^ 15) 
   ,("trillion", 10 ^ 12)
   ,("billion", 10 ^ 9)
   ,("million", 10 ^ 6)
   ,("thousand", 10 ^ 3)]

tokenize :: String -> Words tokenize = words . (map replace) . (map toLower)

   where
     replace c
         | elem c ['a'..'z'] = c
         | otherwise         = ' '

lookupRest :: (Eq a) => a -> [(a,b)] -> Maybe (b, [(a,b)]) lookupRest _ [] = Nothing lookupRest x ((y,z):ws) = if x == y

                         then Just (z, ws)
                         else lookupRest x ws

runState :: State -> TapeValue -> TapeValue runState [] (_, _, word:_) = error $ "Unexpected token: " ++ word runState _ tv@(_, _, []) = tv runState (t:ts) tv@(int, illions, word:wx) =

   case t of
     Transition table state op ->
         case lookup word table of
           Nothing  -> runState ts tv
           Just num -> runState state (op num int, illions, wx)
     Illion state op           ->
         case lookupRest word illions of
           Nothing              -> runState ts tv
           Just (num, illions') -> runState state (op num int, illions', wx)
     Done                      -> tv

stateIllion, stateA, stateB, stateC, stateD, stateE :: State stateIllion = [Illion [Done] (*)]

stateA = [Transition ones stateB (+)

        ,Transition tens stateD (+)
        ,Transition teens stateE (+)]

stateB = [Transition hundred stateC (*)]

        ++ stateIllion

stateC = [Transition ones stateE (+)

        ,Transition tens stateD (+)
        ,Transition teens stateE (+)]
        ++ stateIllion

stateD = [Transition ones stateE (+)]

        ++ stateIllion

stateE = stateIllion ++ [Done]

parseSubWord :: [Symbol] -> Words -> TapeValue parseSubWord illions w = runState stateA (0, illions, w)

parse :: [Symbol] -> Words -> Integer parse _ [] = 0 parse illions wx = let (i, illions', wx') = parseSubWord illions wx

                  in i + parse illions' wx'

integerSpell :: String -> Integer integerSpell wx =

   case tokenize wx of
     ("negative":"zero":[]) -> -0
     ("zero":[])            -> 0
     ("negative":wx')       -> negate $ parse illions wx'
     wx'                    -> parse illions wx'</lang>

J

Define the verb usinv to convert number names to numbers. File number_names.ijs contains the code of number names project. <lang J> NB. standard profile defines tolower and delete extra blanks. load'number_names.ijs'

cut =: #@:[ }.&.> [ (E. <;.1 ]) ,

usinv =: 3 : 0

U =. 'ones' ; }. ENU
A0 =. ;@:(' and'&cut)^:([: +./ ' and '&E.) tolower deb y NB. standardize to us form.
A =. ,&' ones'^:(U -.@e.~ [: {: ;:) A0
B =. ', ' cut A NB. box the comma separated phrases.
C =. ' ' cut L:0 B NB. box words within phrases.
M =. ENU (1000x ^ #@:[ | (i. {:&>)) C  NB. powers of 1000
assert *./ 2 >/\ M NB. the phrases properly ordered.
D=. (<'hundred')&cut&> C
M +/ .*+/"1 ,"2 (([: (* 100 ^ 2 ~: #) (#EN100)|EN100&i.)&>)D

) </lang>

   (-: [&.(us :.usinv))0
1
   (-: [&.(us :.usinv))2340202340220204
1
   (-: [&.:(us :.usinv))2340202340220204x
1

Julia

<lang julia>const stext = ["one", "two", "three", "four", "five",

              "six", "seven", "eight", "nine"]

const teentext = ["eleven", "twelve", "thirteen", "fourteen",

                 "fifteen", "sixteen", "seventeen",
                 "eighteen", "nineteen"]

const tenstext = ["ten", "twenty", "thirty", "forty", "fifty",

                 "sixty", "seventy", "eighty", "ninety"]

const ordstext = ["million", "billion", "trillion",

                 "quadrillion", "quintillion", "sextillion",
                 "septillion", "octillion", "nonillion",
                 "decillion", "undecillion", "duodecillion",
                 "tredecillion", "quattuordecillion", "quindecillion",
                 "sexdecillion", "septendecillion", "octodecillion",
                 "novemdecillion", "vigintillion"]

allnumeric = vcat(

   stext, teentext, tenstext, ordstext, ["minus", "and", "hundred", "thousand", "zero"]

) canon(word) = replace(lowercase(word), r"\-|\,|\.|\:" => "") isnumeric(word) = canon(word) in allnumeric

function parsenumericphrases(txt)

   words = split(strip(txt), r"(\s+)|(\s*\-\s*)")
   phrases, num, alph = Vector{Pair{Bool, Vector{String}}}(), false, false
   for (i, word) in enumerate(words)
       if isnumeric(word) && (num || word != "and")
           if !num
               push!(phrases, Pair(true, String[]))
               num, alph = true, false
           end
           if word != "and"
               push!(phrases[end][2], canon(word))
           end
       else
           if !alph
               push!(phrases, Pair(false, String[]))
               num, alph = false, true
               if length(phrases) > 1 && !occursin(r"\w", words[i - 1][end:end])
                   word = words[i - 1][end] * " " * word
               end
           end
           push!(phrases[end][2], word)
       end
   end
   return phrases

end

function sumones(word, total)

   n = something(findfirst(x -> x == word, stext), 0)
   x = something(findfirst(x -> x == word, teentext), 0)
   (x > 0) && (n += (10 + x))
   n += something(findfirst(x -> x == word, tenstext), 0) * 10
   return n + total

end

sumhundreds(word, total) = word == "hundred" ? total *= 100 : total

function summils(word, miltotal, onestotal)

   if word == "thousand"
       return miltotal + onestotal * 1000, 0
   elseif (x = something(findfirst(x -> x == word, ordstext), 0)) > 0
       return miltotal + onestotal * 1000^(x + 1), 0
   else
       return miltotal, onestotal
   end

end

function texttointeger(txt)

   phrasepairs, outputphrases = parsenumericphrases(txt), String[]
   for phrase in phrasepairs
       if phrase[1]  # numeric phrase
           wordarray, sign, onestotal, miltotal = phrase[2], 1, 0, 0
           for word in wordarray
               onestotal = sumones(word, onestotal)
               onestotal = sumhundreds(word, onestotal)
               miltotal, onestotal = summils(word, miltotal, onestotal)
           end
           push!(outputphrases, string(sign * (onestotal + miltotal)))
       else # non-numeric phrase
           push!(outputphrases, join(phrase[2], " "))
       end
   end
   return replace(join(outputphrases, " "), r"([\w\d])\s(\,|\:|\;|\.)" => s"\1\2")

end

const examples = """ One Hundred and One Dalmatians Two Thousand and One: A Space Odyssey Four Score And Seven Years Ago twelve dozen is one hundred forty-four, aka one gross two hundred pairs of socks Always give one hundred and ten percent effort Change due: zero dollars and thirty-seven cents One hour, fifty-nine minutes, forty point two seconds Two Thousand Nineteen Two Thousand Zero Hundred and Nineteen Two Thousand Ten Nine one thousand one ninety nine thousand nine hundred ninety nine five hundred and twelve thousand, six hundred and nine two billion, one hundred One Thousand One Hundred Eleven Eleven Hundred Eleven one hundred eleven billion one hundred eleven Eight Thousand Eight Hundred Eighty-Eight Eighty-Eight Hundred Eighty-Eight one quadrillion, two trillion, three billion, four million, five thousand six """

for txt in split(strip(examples), r"\n")

   println(txt, " => ", texttointeger(txt))

end

</lang>

Output:
One Hundred and One Dalmatians => 101 Dalmatians
Two Thousand and One: A Space Odyssey => 2001: A Space Odyssey
Four  Score  And  Seven  Years  Ago => 4 Score 7 Years Ago
twelve dozen is one hundred forty-four, aka one gross => 12 dozen is 144, aka 1 gross
two hundred pairs of socks => 200 pairs of socks
Always give one hundred and ten percent effort => Always give 110 percent effort
Change due: zero dollars and thirty-seven cents => Change due: 0 dollars and 37 cents
One hour, fifty-nine minutes, forty point two seconds => 1 hour, 59 minutes, 40 point 2 seconds
Two Thousand Nineteen => 2019
Two Thousand Zero Hundred and Nineteen => 2019
Two Thousand Ten Nine => 2019
one thousand one => 1001
ninety nine thousand nine hundred ninety nine => 99999
five hundred and twelve thousand, six hundred and nine => 512609
two billion, one hundred => 2000000100
One Thousand One Hundred Eleven => 1111
Eleven Hundred Eleven => 1111
one hundred eleven billion one hundred eleven => 111000000111
Eight Thousand Eight Hundred Eighty-Eight => 8888
Eighty-Eight Hundred Eighty-Eight => 8888
one quadrillion, two trillion, three billion, four million, five thousand six => 1002003004005006

Kotlin

<lang scala>// version 1.1.2

val names = mapOf<String, Long>(

   "one" to 1,
   "two" to 2,
   "three" to 3,
   "four" to 4,
   "five" to 5,
   "six" to 6,
   "seven" to 7,
   "eight" to 8,
   "nine" to 9,
   "ten" to 10,
   "eleven" to 11,
   "twelve" to 12,
   "thirteen" to 13,
   "fourteen" to 14,
   "fifteen" to 15,
   "sixteen" to 16,
   "seventeen" to 17,
   "eighteen" to 18,
   "nineteen" to 19,
   "twenty" to 20,
   "thirty" to 30,
   "forty" to 40,
   "fifty" to 50,
   "sixty" to 60,
   "seventy" to 70,
   "eighty" to 80,
   "ninety" to 90,
   "hundred" to 100,
   "thousand" to 1_000,
   "million" to 1_000_000,
   "billion" to 1_000_000_000,
   "trillion" to 1_000_000_000_000L,
   "quadrillion" to 1_000_000_000_000_000L,
   "quintillion" to 1_000_000_000_000_000_000L

)

val zeros = listOf("zero", "nought", "nil", "none", "nothing")

fun nameToNum(name: String): Long {

   var text = name.trim().toLowerCase()
   val isNegative = text.startsWith("minus ")
   if (isNegative) text = text.drop(6)
   if (text.startsWith("a ")) text = "one" + text.drop(1)
   val words = text.split(",", "-", " and ", " ").filter { it != "" }
   val size = words.size
   if (size == 1 && words[0] in zeros) return 0L
   var multiplier = 1L
   var lastNum = 0L
   var sum = 0L
   for (i in size - 1 downTo 0) {
       val num: Long? = names[words[i]]
       if (num == null)
           throw IllegalArgumentException("'${words[i]}' is not a valid number")
       else if (num == lastNum)
           throw IllegalArgumentException("'$name' is not a well formed numeric string")
       else if (num >= 1000) {
           if (lastNum >= 100)
               throw IllegalArgumentException("'$name' is not a well formed numeric string")
           multiplier = num
           if (i == 0) sum += multiplier
       } else if (num >= 100) {
           multiplier *= 100
           if (i == 0) sum += multiplier
       } else if (num >= 20) {
           if (lastNum in 10..90)
               throw IllegalArgumentException("'$name' is not a well formed numeric string")
           sum += num * multiplier
       } else {
           if (lastNum in 1..90)
               throw IllegalArgumentException("'$name' is not a well formed numeric string")
           sum += num * multiplier
       }
       lastNum = num
   }
   if (isNegative && sum == -sum)
       return Long.MIN_VALUE
   else if (sum < 0L)
       throw IllegalArgumentException("'$name' is outside the range of a Long integer")
   return if (isNegative) -sum else sum

}

fun main(args: Array<String>) {

   val names = arrayOf(
       "none",
       "one",
       "twenty-five",
       "minus one hundred and seventeen",
       "hundred and fifty-six",
       "minus two thousand two",
       "nine thousand, seven hundred, one",
       "minus six hundred and twenty six thousand, eight hundred and fourteen",
       "four million, seven hundred thousand, three hundred and eighty-six",
       "fifty-one billion, two hundred and fifty-two million, seventeen thousand, one hundred eighty-four",
       "two hundred and one billion, twenty-one million, two thousand and one",
       "minus three hundred trillion, nine million, four hundred and one thousand and thirty-one",
       "seventeen quadrillion, one hundred thirty-seven",
       "a quintillion, eight trillion and five",
       "minus nine quintillion, two hundred and twenty-three quadrillion, three hundred and seventy-two trillion, thirty-six billion, eight hundred and fifty-four million, seven hundred and seventy-five thousand, eight hundred and eight"
   )
   for (name in names) println("${"%20d".format(nameToNum(name))} = $name")

}</lang>

Output:
                   0 = none
                   1 = one
                  25 = twenty-five
                -117 = minus one hundred and seventeen
                 156 = hundred and fifty-six
               -2002 = minus two thousand two
                9701 = nine thousand, seven hundred, one
             -626814 = minus six hundred and twenty six thousand, eight hundred and fourteen
             4700386 = four million, seven hundred thousand, three hundred and eighty-six
         51252017184 = fifty-one billion, two hundred and fifty-two million, seventeen thousand, one hundred eighty-four
        201021002001 = two hundred and one billion, twenty-one million, two thousand and one
    -300000009401031 = minus three hundred trillion, nine million, four hundred and one thousand and thirty-one
   17000000000000137 = seventeen quadrillion, one hundred thirty-seven
 1000008000000000005 = a quintillion, eight trillion and five
-9223372036854775808 = minus nine quintillion, two hundred and twenty-three quadrillion, three hundred and seventy-two trillion, thirty-six billion, eight hundred and fifty-four million, seven hundred and seventy-five thousand, eight hundred and eight

Nim

Translation of: Kotlin

<lang Nim>import re, sequtils, strformat, strutils, tables

const Names = {"one": 1u64,

              "two":         2u64,
              "three":       3u64,
              "four":        4u64,
              "five":        5u64,
              "six":         6u64,
              "seven":       7u64,
              "eight":       8u64,
              "nine":        9u64,
              "ten":         10u64,
              "eleven":      11u64,
              "twelve":      12u64,
              "thirteen":    13u64,
              "fourteen":    14u64,
              "fifteen":     15u64,
              "sixteen":     16u64,
              "seventeen":   17u64,
              "eighteen":    18u64,
              "nineteen":    19u64,
              "twenty":      20u64,
              "thirty":      30u64,
              "forty":       40u64,
              "fifty":       50u64,
              "sixty":       60u64,
              "seventy":     70u64,
              "eighty":      80u64,
              "ninety":      90u64,
              "hundred":     100u64,
              "thousand":    1000u64,
              "million":     1000000u64,
              "billion":     1000000000u64,
              "trillion":    1000000000000u64,
              "quadrillion": 1000000000000000u64,
              "quintillion": 1000000000000000000u64}.toTable

let Seps = re",|-| and | " const Zeros = ["zero", "nought", "nil", "none", "nothing"]

template emitError(msg: string) = raise newException(ValueError, msg)


proc nameToNum(name: string): int64 =

 var text = name.strip().toLowerAscii
 let isNegative = text.startsWith("minus ")
 if isNegative: text.delete(0, 5)
 if text.startsWith("a"):
   text = "one" & text[1..^1]
 let words = text.split(Seps).filterIt(it.len != 0)
 if words.len == 1 and words[0] in Zeros:
   return 0
 var
   multiplier = 1u64
   lastNum, sum = 0u64
 for i in countdown(words.high, 0):
   let num = Names.getOrDefault(words[i], 0)
   if num == 0:
     emitError(&"'{words[i]}' is not a valid number")
   elif num == lastNum:
     emitError(&"'{name}' is not a well formed numeric string")
   elif num >= 1000:
     if lastNum >= 100:
       emitError(&"'{name}' is not a well formed numeric string")
     multiplier = num
     if i == 0: sum += multiplier
   elif num >= 100:
     multiplier *= 100
     if i == 0: sum += multiplier
   elif num >= 20:
     if lastNum in 10u64..90u64:
       emitError(&"'{name}' is not a well formed numeric string")
     sum += num * multiplier
   else:
     if lastNum in 1u64..90u64:
       emitError(&"'{name}' is not a well formed numeric string")
     sum += num * multiplier
   lastNum = num
 if isNegative and sum == uint64(int64.high) + 1:
   return int64.low
 if sum > uint64(int64.high):
   emitError(&"'$name' is outside the range of a 64 bits integer")
 result = if isNegative: -int64(sum) else: int64(sum)


when isMainModule:

 let names = [
   "none",
   "one",
   "twenty-five",
   "minus one hundred and seventeen",
   "hundred and fifty-six",
   "minus two thousand two",
   "nine thousand, seven hundred, one",
   "minus six hundred and twenty six thousand, eight hundred and fourteen",
   "four million, seven hundred thousand, three hundred and eighty-six",
   "fifty-one billion, two hundred and fifty-two million, seventeen thousand, one hundred eighty-four",
   "two hundred and one billion, twenty-one million, two thousand and one",
   "minus three hundred trillion, nine million, four hundred and one thousand and thirty-one",
   "seventeen quadrillion, one hundred thirty-seven",
   "a quintillion, eight trillion and five",
   "minus nine quintillion, two hundred and twenty-three quadrillion, three hundred and seventy-two trillion, thirty-six billion, eight hundred and fifty-four million, seven hundred and seventy-five thousand, eight hundred and eight"]

for name in names:

 echo ($nametoNum(name)).align(20), " = ", name</lang>
Output:
                   0 = none
                   1 = one
                  25 = twenty-five
                -117 = minus one hundred and seventeen
                 156 = hundred and fifty-six
               -2002 = minus two thousand two
                9701 = nine thousand, seven hundred, one
             -626814 = minus six hundred and twenty six thousand, eight hundred and fourteen
             4700386 = four million, seven hundred thousand, three hundred and eighty-six
         51252017184 = fifty-one billion, two hundred and fifty-two million, seventeen thousand, one hundred eighty-four
        201021002001 = two hundred and one billion, twenty-one million, two thousand and one
    -300000009401031 = minus three hundred trillion, nine million, four hundred and one thousand and thirty-one
   17000000000000137 = seventeen quadrillion, one hundred thirty-seven
 1000008000000000005 = a quintillion, eight trillion and five
-9223372036854775808 = minus nine quintillion, two hundred and twenty-three quadrillion, three hundred and seventy-two trillion, thirty-six billion, eight hundred and fifty-four million, seven hundred and seventy-five thousand, eight hundred and eight

Perl

<lang perl>use strict; use warnings; use feature 'say';

my $phrases_with_numbers = <<'END'; One Hundred and One Dalmatians Two Thousand and One: A Space Odyssey

Four Score And Seven Years Ago twelve dozen is one hundred forty-four, aka one gross two hundred pairs of socks Always give one hundred and ten percent effort Change due: zero dollars and thirty-seven cents

One hour, fifty-nine minutes, forty point two seconds π ≅ three point one four one five nine END

my $pure_numbers = <<'END'; Twenty Nineteen Two Thousand Nineteen Two Thousand Zero Hundred and Nineteen Two Thousand Ten Nine

one thousand one ninety nine thousand nine hundred ninety nine five hundred and twelve thousand, six hundred and nine two billion, one hundred

One Thousand One Hundred Eleven Eleven Hundred Eleven one hundred eleven billion one hundred eleven Eight Thousand Eight Hundred Eighty-Eight Eighty-Eight Hundred Eighty-Eight

one quadrillion, two trillion, three billion, four million, five thousand six END

my %nums = (

   zero        => 0,   one       => 1,     two      => 2,    three    => 3,
   four        => 4,   five      => 5,     six      => 6,    seven    => 7,
   eight       => 8,   nine      => 9,     ten      => 10,   eleven   => 11,
   twelve      => 12,  thirteen  => 13,    fourteen => 14,   fifteen  => 15,
   sixteen     => 16,  seventeen => 17,    eighteen => 18,   nineteen => 19,
   twenty      => 20,  thirty    => 30,    forty    => 40,   fifty    => 50,
   sixty       => 60,  seventy   => 70,    eighty   => 80,   ninety   => 90,
   hundred     => 100, thousand  => 1_000, million  => 1_000_000,
   billion     => 1_000_000_000,           trillion => 1_000_000_000_000,
   quadrillion => 1_000_000_000_000_000

);

  1. Groupings for thousands, millions, ... quadrillions

my $groups = qr/\d{4}|\d{7}|\d{10}|\d{13}|\d{16}/;

sub sum {

   my($values) = @_;
   my $sum = 0;
   $sum += $_ for split ' ', $values;
   $sum;

}

sub squeeze {

   my($str) = @_;
   $str =~ s/[\-\s]+/ /g;
   $str =~ s/^\s*(.*?)\s*$/$1/r;

}

  1. commify larger numbers for readabilty

sub comma {

   my($i) = @_;
   return $i if length($i) < 5;
   reverse ((reverse $i) =~ s/(.{3})/$1,/gr) =~ s/^,//r

}

sub numify {

   my($str) = @_;
   $str =~ tr/A-Z/a-z/;
   $str = squeeze($str);
   $str =~ s/(.)(punct:)/$1 $2/g;
   foreach my $key (keys %nums) { $str =~ s/ \b $key \b /$nums{$key}/gx }
   $str =~ s/(\d+) \s+ (?=\d)/$1/gx if $str =~ /point (\d )+/;
   $str =~ s/(\d+) \s+ score / $1 * 20 /egx;
   $str =~ s/(\d) (?:,|and) (\d)/$1 $2/g;
   $str =~ s/\b (\d) \s+ 100 \s+ (\d\d) \s+ (\d) \s+    ($groups) \b / ($1 * 100 + $2 + $3) * $4 /egx;
   $str =~ s/\b (\d) \s+ 100 \s+ (\d{1,2}) \s+          ($groups) \b / ($1 * 100 + $2) * $3      /egx;
   $str =~ s/\b (\d) \s+ 100 \s+                        ($groups) \b /  $1 * 100 * $2            /egx;
   $str =~ s/\b      \s+ 100 \s+ (\d\d) \s+ (\d) \s+    ($groups) \b / ($1 + 100 + $2) * $3      /egx;
   $str =~ s/\b      \s+ 100 \s+ (\d{1,2}) \s+          ($groups) \b / ($1 + 100     ) * $2      /egx;
   $str =~ s/\b      \s+ 100 \s+                        ($groups) \b /  $1 * 100                 /egx;
   $str =~ s/\b                  (\d\d) \s+ (\d) \s+    ($groups) \b / ($1 + $2) * $3            /egx;
   $str =~ s/\b                  (\d{1,2}) \s+          ($groups) \b /  $1 * $2                  /egx;
   $str =~ s/\b                  (\d\d) \s+ (\d) \s+ 100          \b / ($1 + $2) * 100           /egx;
   $str =~ s/\b                  (\d{1,2}) \s+ 100                \b /  $1 * 100                 /egx;
   $str =~ s/\b                  (\d{2}) \s+ (\d{2})              \b /  $1 * 100 + $2            /egx;
   $str =~ s/((?:\d+ )*\d+)/sum $1/eg;
   $str =~ s/(\d+) \s+ pairs.of        /   $1 *  2 /egx;
   $str =~ s/(\d+) \s+ dozen           /   $1 * 12 /egx;
   $str =~ s/(\d+) \s+ point \s+ (\d+) /   $1.$2   /gx;
   $str =~ s/(\d+) \s+ percent         /   $1%     /gx;
   $str =~ s/(\d+) \s+ dollars         / \$$1      /gx;
   $str =~ s/(\d+) \s+ cents           /   $1¢     /gx;
   squeeze $str;

}

say $_ . ' --> ' . numify($_) for grep { $_ } split "\n", $phrases_with_numbers; say $_ . ' --> ' . comma numify($_) for grep { $_ } split "\n", $pure_numbers;</lang>

One Hundred and One Dalmatians --> 101 dalmatians
Two Thousand and One: A Space Odyssey --> 2001 : a space odyssey
Four  Score  And  Seven  Years  Ago --> 87 years ago
twelve dozen is one hundred forty-four, aka one gross --> 144 is 144 , aka 1 gross
two hundred pairs of socks --> 400 socks
Always give one hundred and ten percent effort --> always give 110% effort
Change due: zero dollars and thirty-seven cents --> change due : $0 and 37¢
One hour, fifty-nine minutes, forty point two seconds --> 1 hour , 509 minutes , 40.2 seconds
π ≅ three point one four one five nine --> π ≅ 3.14159
Twenty Nineteen --> 2019
Two Thousand Nineteen --> 2019
Two Thousand Zero Hundred and Nineteen --> 2019
Two Thousand Ten Nine --> 2019
one thousand one --> 1001
ninety nine thousand nine hundred ninety nine --> 99,999
five hundred and twelve thousand, six hundred and nine --> 512,609
two billion, one hundred --> 2,000,000,100
One Thousand One Hundred Eleven --> 1111
Eleven Hundred Eleven --> 1111
one hundred eleven billion one hundred eleven --> 111,000,000,111
Eight Thousand Eight Hundred Eighty-Eight --> 8888
Eighty-Eight Hundred Eighty-Eight --> 8888
one quadrillion, two trillion, three billion, four million, five thousand six --> 1,002,003,004,005,006

Phix

Uses Number_names as an executable library. <lang Phix>-- -- demo\rosetta\Names_to_numbers.exw -- include demo\rosetta\Number_names.exw

constant {tokens,tokvals} = columnize({{"zero",0},{"one",1},{"two",2},{"three",3},{"four",4},{"five",5},{"six",6},

                                      {"seven",7},{"eight",8},{"nine",9},{"ten",10},
                                      {"eleven",11},{"twelve",12},{"thirteen",13},{"fourteen",14},{"fifteen",15},
                                      {"sixteen",16},{"seventeen",17},{"eighteen",18},{"nineteen",19},
                                      {"twenty",20},{"thirty",30},{"forty",40},{"fifty",50},{"sixty",60},
                                      {"seventy",70},{"eighty",80},{"ninety",90},{"hundred",100},{"thousand",1e3},
                                      {"million",1e6},{"billion",1e9},{"trillion",1e12}})

function parse(string s) sequence words integer negmul = 1, hund = 0 atom total = 0, k

   s = substitute(s,",","")
   s = substitute(s," and "," ")
   s = substitute(s,"-"," ")
   words = split(s)
   if length(words)=0 then return "invalid" end if
   if words[1]=="minus" then
       negmul = -1
       words = words[2..$]
   end if
   for i=1 to length(words) do
       k = find(words[i],tokens)
       if k=0 then
           if words[i]!="point" then return "invalid" end if
           total += hund
           hund = 0
           integer tens = 10
           for j=i+1 to length(words) do
               k = find(words[j],tokens)
               if k=0 then return "invalid" end if
               k = tokvals[k]
               if k>9 then return "invalid" end if
               total += k/tens
               tens *= 10
           end for
           exit
       end if
       k = tokvals[k]
       if k<100 then
           hund += k
       elsif k=100 then
           hund *= k
       else
           total += hund*k
           hund = 0
       end if
   end for
   return negmul*(total+hund)  

end function

atom si

   for i=1 to length(Samples) do
       si = Samples[i]
       string s = spell(si)

-- if parse(s)=si then

       if abs(parse(s)-si)<1e-6 then
           s = "<==> "&s
       else
           s = "???? "&s
       end if
       printf(1,"%18s %s\n",{smartp(si),s})
   end for</lang>
Output:
                99 <==> ninety-nine
               300 <==> three hundred
               310 <==> three hundred and ten
               417 <==> four hundred and seventeen
              1501 <==> one thousand, five hundred and one
             12609 <==> twelve thousand, six hundred and nine
   200000000000100 <==> two hundred trillion, and one hundred
   999999999999999 <==> nine hundred and ninety-nine trillion, nine hundred and ninety-nine billion, nine hundred and ninety-nine million, nine hundred and ninety-nine thousand, nine hundred and ninety-nine
  -123456787654321 <==> minus one hundred and twenty-three trillion, four hundred and fifty-six billion, seven hundred and eighty-seven million, six hundred and fifty-four thousand, three hundred and twenty-one
   102003000400005 <==> one hundred and two trillion, three billion, four hundred thousand, and five
        1020030004 <==> one billion, twenty million, thirty thousand, and four
            102003 <==> one hundred and two thousand, and three
               102 <==> one hundred and two
                 1 <==> one
                 0 <==> zero
                -1 <==> minus one
               -99 <==> minus ninety-nine
             -1501 <==> minus one thousand, five hundred and one
              1234 <==> one thousand, two hundred and thirty-four
             12.34 <==> twelve point three four
        10000001.2 <==> ten million, and one point two
             0.001 <==> zero point zero zero one
        -2.7182818 <==> minus two point seven one eight two eight one eight
      201021002001 <==> two hundred and one billion, twenty-one million, two thousand, and one
      -20102100200 <==> minus twenty billion, one hundred and two million, one hundred thousand, and two hundred
        2010210020 <==> two billion, ten million, two hundred and ten thousand, and twenty
        -201021002 <==> minus two hundred and one million, twenty-one thousand, and two
          20102100 <==> twenty million, one hundred and two thousand, and one hundred
          -2010210 <==> minus two million, ten thousand, two hundred and ten
            201021 <==> two hundred and one thousand, and twenty-one
            -20102 <==> minus twenty thousand, one hundred and two
              2010 <==> two thousand, and ten
              -201 <==> minus two hundred and one
                20 <==> twenty
                -2 <==> minus two

Python

This example assumes that the module from Number_names#Python is stored as spell_integer.py.

The example understands the textual format generated from number-to-names module.

Note: This example and Number_names#Python need to be kept in sync <lang python>from spell_integer import spell_integer, SMALL, TENS, HUGE

def int_from_words(num):

   words = num.replace(',',).replace(' and ', ' ').replace('-', ' ').split()
   if words[0] == 'minus':
       negmult = -1
       words.pop(0)
   else:
       negmult = 1
   small, total = 0, 0
   for word in words:
       if word in SMALL:
           small += SMALL.index(word)
       elif word in TENS:
           small += TENS.index(word) * 10
       elif word == 'hundred':
           small *= 100
       elif word == 'thousand':
           total += small * 1000
           small = 0
       elif word in HUGE:
           total += small * 1000 ** HUGE.index(word)
           small = 0
       else:
           raise ValueError("Don't understand %r part of %r" % (word, num))
   return negmult * (total + small)


if __name__ == '__main__':

   # examples
   for n in range(-10000, 10000, 17):
       assert n == int_from_words(spell_integer(n))
   for n in range(20):
       assert 13**n == int_from_words(spell_integer(13**n))
   
   print('\n##\n## These tests show <==> for a successful round trip, otherwise <??>\n##\n') 
   for n in (0, -3, 5, -7, 11, -13, 17, -19, 23, -29):
       txt = spell_integer(n)
       num = int_from_words(txt)
       print('%+4i <%s> %s' % (n, '==' if n == num else '??', txt))
   print()  
   
   n = 201021002001
   while n:
       txt = spell_integer(n)
       num = int_from_words(txt)
       print('%12i <%s> %s' % (n, '==' if n == num else '??', txt))
       n //= -10
   txt = spell_integer(n)
   num = int_from_words(txt)
   print('%12i <%s> %s' % (n, '==' if n == num else '??', txt))
   print()</lang>
Output:
##
## These tests show <==> for a successful round trip, otherwise <??>
##

  +0 <==> zero
  -3 <==> minus three
  +5 <==> five
  -7 <==> minus seven
 +11 <==> eleven
 -13 <==> minus thirteen
 +17 <==> seventeen
 -19 <==> minus nineteen
 +23 <==> twenty-three
 -29 <==> minus twenty-nine

201021002001 <==> two hundred and one billion, twenty-one million, two thousand, and one
-20102100201 <==> minus twenty billion, one hundred and two million, one hundred thousand, two hundred and one
  2010210020 <==> two billion, ten million, two hundred and ten thousand, and twenty
  -201021002 <==> minus two hundred and one million, twenty-one thousand, and two
    20102100 <==> twenty million, one hundred and two thousand, and one hundred
    -2010210 <==> minus two million, ten thousand, two hundred and ten
      201021 <==> two hundred and one thousand, and twenty-one
      -20103 <==> minus twenty thousand, one hundred and three
        2010 <==> two thousand, and ten
        -201 <==> minus two hundred and one
          20 <==> twenty
          -2 <==> minus two
           0 <==> zero

Racket

Extension of the number to names code:

<lang racket>

  1. lang racket

(define smalls

 (map symbol->string
      '(zero one two three four five six seven eight nine ten eleven twelve
        thirteen fourteen fifteen sixteen seventeen eighteen nineteen)))

(define tens

 (map symbol->string
      '(zero ten twenty thirty forty fifty sixty seventy eighty ninety)))

(define larges

 (map symbol->string
      '(thousand million billion trillion quadrillion quintillion sextillion
        septillion octillion nonillion decillion undecillion duodecillion
        tredecillion quattuordecillion quindecillion sexdecillion
        septendecillion octodecillion novemdecillion vigintillion)))

(define (integer->english n)

 (define (step div suffix separator [subformat integer->english])
   (define-values [q r] (quotient/remainder n div))
   (define S (if suffix (~a (subformat q) " " suffix) (subformat q)))
   (if (zero? r) S (~a S separator (integer->english r))))
 (cond [(< n 0) (~a "negative " (integer->english (- n)))]
       [(< n 20) (list-ref smalls n)]
       [(< n 100) (step 10 #f "-" (curry list-ref tens))]
       [(< n 1000) (step 100 "hundred" " and ")]
       [else (let loop ([N 1000000] [D 1000] [unit larges])
               (cond [(null? unit)
                      (error 'integer->english "number too big: ~e" n)]
                     [(< n N) (step D (car unit) ", ")]
                     [else (loop (* 1000 N) (* 1000 D) (cdr unit))]))]))

(define (english->integer str)

 (define (word->integer word)
   (or (for/first ([s (in-list smalls)] [n (in-naturals)]
                   #:when (equal? word s))
         n)
       (for/first ([s (in-list tens)] [n (in-naturals)]
                   #:when (equal? word s))
         (* 10 n))
       (for/first ([s (in-list larges)] [n (in-naturals 1)]
                   #:when (equal? word s))
         (expt 10 (* 3 n)))
       0))
 (for/sum ([part (in-list (string-split str #rx" *, *"))])
   (let loop ([part (regexp-split #rx"[ -]" part)] [sum 0])
     (match part
       [(list n)
        (let ([n (word->integer n)]) (if (< 999 n) (* sum n) (+ sum n)))]
       [(list n "hundred" rest ...)
        (loop rest (+ sum (* 100 (word->integer n))))]
       [(list n rest ...)
        (loop rest (+ sum (word->integer n)))]
       [_ sum]))))

(for ([size 10])

 (define e   (expt 10 size))
 (define n   (+ (* e (random e)) (random e)))
 (define eng (integer->english n))
 (define n2  (english->integer eng))
 (if (= n2 n)
   (printf "~s <-> ~a\n" n eng)
   (printf "Fail: ~s -> ~a -> ~s\n" n eng n2)))

</lang>

Output:
0 <-> zero
90 <-> ninety
361 <-> three hundred and sixty-one
528142 <-> five hundred and twenty-eight thousand, one hundred and forty-two
92596865 <-> ninety-two million, five hundred and ninety-six thousand, eight hundred and sixty-five
690856444 <-> six hundred and ninety million, eight hundred and fifty-six thousand, four hundred and forty-four
245479718757 <-> two hundred and forty-five billion, four hundred and seventy-nine million, seven hundred and eighteen thousand, seven hundred and fifty-seven
37308165785935 <-> thirty-seven trillion, three hundred and eight billion, one hundred and sixty-five million, seven hundred and eighty-five thousand, nine hundred and thirty-five
7878883296406183 <-> seven quadrillion, eight hundred and seventy-eight trillion, eight hundred and eighty-three billion, two hundred and ninety-six million, four hundred and six thousand, one hundred and eighty-three
552966175718680570 <-> five hundred and fifty-two quadrillion, nine hundred and sixty-six trillion, one hundred and seventy-five billion, seven hundred and eighteen million, six hundred and eighty thousand, five hundred and seventy

Raku

(formerly Perl 6)

Translation of: Perl

<lang perl6>my $phrases-with-numbers = q:to/END/; One Hundred and One Dalmatians Two Thousand and One: A Space Odyssey

Four Score And Seven Years Ago twelve dozen is one hundred forty-four, aka one gross two hundred pairs of socks Always give one hundred and ten percent effort Change due: zero dollars and thirty-seven cents

One hour, fifty-nine minutes, forty point two seconds π ≅ three point one four one five nine END

my $pure-numbers = q:to/END/; Twenty Nineteen Two Thousand Nineteen Two Thousand Zero Hundred and Nineteen Two Thousand Ten Nine

one thousand one ninety nine thousand nine hundred ninety nine five hundred and twelve thousand, six hundred and nine two billion, one hundred

One Thousand One Hundred Eleven Eleven Hundred Eleven one hundred eleven billion one hundred eleven Eight Thousand Eight Hundred Eighty-Eight Eighty-Eight Hundred Eighty-Eight

Forty-two quintillion, one quadrillion, two trillion, three billion, four million, five thousand six END

my %nums = (

   zero        => 0,     one        => 1,     two         => 2,     three    => 3,
   four        => 4,     five       => 5,     six         => 6,     seven    => 7,
   eight       => 8,     nine       => 9,     ten         => 10,    eleven   => 11,
   twelve      => 12,    thirteen   => 13,    fourteen    => 14,    fifteen  => 15,
   sixteen     => 16,    seventeen  => 17,    eighteen    => 18,    nineteen => 19,
   twenty      => 20,    thirty     => 30,    forty       => 40,    fifty    => 50,
   sixty       => 60,    seventy    => 70,    eighty      => 80,    ninety   => 90,
   hundred     => 100,   thousand   => 1_000, million     => 1_000_000,
   billion     => 1_000_000_000,              trillion    => 1_000_000_000_000,
   quadrillion => 1_000_000_000_000_000,      quintillion => 1_000_000_000_000_000_000

);

  1. groupings: thousand million billion trillion quadrillion quintillion

my token groups { \d**4 | \d**7 | \d**10 | \d**13 | \d**16 | \d**19 };

  1. remove hyphens/spaces: leading, trailing, multiple

sub squeeze ($str is copy) { $str ~~ s:g/'-' | \s+ / /; $str .=trim }

  1. commify larger numbers for readabilty

sub comma { $^i.chars > 4 ?? $^i.flip.comb(3).join(',').flip !! $^i }

sub numify ($str is copy) {

   $str = squeeze $str.lc;
   $str ~~ s:g/(.)(<punct>)/$0 $1/;
   for %nums.kv -> $word, $number { $str ~~ s:g/ <|w> $word <|w> / $number / }
   $str ~~ s:g/(\d+)<ws> <?before \d>/$0/ if $str ~~ /(point )<ws>[(\d)<ws>]+$/;
   $str ~~ s:g/(\d+) <ws> 'score' / {$0 * 20} /;
   $str ~~ s:g/(\d) <ws> [','|'and'] <ws> (\d)/$0 $1/;
   $str ~~ s:g/ <|w> (\d) <ws> 100 <ws> (\d\d) <ws> (\d) <ws>     (<groups>) <|w> / {($0 * 100 + $1 + $2) * $3} /;
   $str ~~ s:g/ <|w> (\d) <ws> 100 <ws> (\d ** 1..2)     <ws>     (<groups>) <|w> / {($0 * 100 + $1) * $2}      /;
   $str ~~ s:g/ <|w> (\d) <ws> 100                       <ws>     (<groups>) <|w> / { $0 * 100 * $1}            /;
   $str ~~ s:g/ <|w>      <ws> 100 <ws> (\d\d) <ws> (\d) <ws>     (<groups>) <|w> / {($0 + 100 + $1) * $2}      /;
   $str ~~ s:g/ <|w>      <ws> 100 <ws> (\d ** 1..2)     <ws>     (<groups>) <|w> / {($0 + 100     ) * $1}      /;
   $str ~~ s:g/ <|w>      <ws> 100                       <ws>     (<groups>) <|w> / { $0 * 100}                 /;
   $str ~~ s:g/ <|w>              (\d\d) <ws> (\d)       <ws>     (<groups>) <|w> / {($0 + $1) * $2}            /;
   $str ~~ s:g/ <|w>              (\d ** 1..2)           <ws>     (<groups>) <|w> / { $0 * $1}                  /;
   $str ~~ s:g/ <|w>              (\d\d) <ws> (\d)       <ws> 100            <|w> / {($0 + $1) * 100}           /;
   $str ~~ s:g/ <|w>              (\d ** 1..2)           <ws> 100            <|w> / { $0 * 100}                 /;
   $str ~~ s:g/ <|w>              (\d ** 2)<ws>(\d ** 2)                     <|w> / { $0 * 100 + $1}            /;
   $str ~~ s:g/( [\d+<ws>]* \d+ ) / {[+] $0.split: ' '} /;
   $str ~~ s:g/(\d+) <ws> 'pairs of'         /  {$0 *  2} /;
   $str ~~ s:g/(\d+) <ws> 'dozen'            /  {$0 * 12} /;
   $str ~~ s:g/(\d+) <ws> 'point' <ws> (\d+) /   $0.$1    /;
   $str ~~ s:g/(\d+) <ws> 'percent'          /   $0%      /;
   $str ~~ s:g/(\d+) <ws> 'dollars'          / \$$0       /;
   $str ~~ s:g/(\d+) <ws> 'cents'            /   $0¢      /;
   squeeze $str;

}

say $_ ~ ' --> ' ~ .&numify for $phrases-with-numbers.split("\n").grep: *.so; say $_ ~ ' --> ' ~ .&numify.&comma for $pure-numbers.split("\n").grep: *.so;</lang>

Output:
One Hundred and One Dalmatians --> 101 dalmatians
Two Thousand and One: A Space Odyssey --> 2001 : a space odyssey
Four  Score  And  Seven  Years  Ago   --> 87 years ago
twelve dozen is one hundred forty-four, aka one gross --> 144 is 144 , aka 1 gross
two hundred pairs of socks --> 400 socks
Always give one hundred and ten percent effort --> always give 110% effort
Change due: zero dollars and thirty-seven cents --> change due : $0 and 37¢
One hour, fifty-nine minutes, forty point two seconds --> 1 hour , 59 minutes , 40.2 seconds
π ≅ three point one four one five nine --> π ≅ 3.14159
Twenty Nineteen --> 2019
Two Thousand Nineteen --> 2019
Two Thousand Zero Hundred and Nineteen --> 2019
Two Thousand Ten Nine --> 2019
one thousand one --> 1001
ninety nine thousand nine hundred ninety nine --> 99,999
five hundred and twelve thousand, six hundred and nine --> 512,609
two billion, one hundred --> 2,000,000,100
One Thousand One Hundred Eleven --> 1111
Eleven Hundred Eleven --> 1111
one hundred eleven billion one hundred eleven --> 111,000,000,111
Eight Thousand Eight Hundred Eighty-Eight --> 8888
Eighty-Eight Hundred Eighty-Eight --> 8888
Forty-two quintillion, one quadrillion, two trillion, three billion, four million, five thousand six --> 42,001,002,003,004,005,006

Ruby

This solution uses "Number names" from here

Translation of: Python

<lang ruby>require 'number_names'

def int_from_words(num)

 words = num.downcase.gsub(/(,| and |-)/,' ').split
 if words[0] =~ /(minus|negative)/
   negmult = -1
   words.shift
 else
   negmult = 1
 end
 small, total = 0, 0
 for word in words
   case word
   when *SMALL
     small += SMALL.index(word)
   when *TENS
     small += TENS.index(word) * 10
   when 'hundred'
     small *= 100
   when 'thousand'
     total += small * 1000
     small = 0
   when *BIG
     total += small * 1000 ** BIG.index(word)
     small = 0
   else
     raise ArgumentError, "Don't understand %s part of %s" % [word, num]
   end
 end
 negmult * (total + small)

end</lang>

Examples: <lang ruby>for n in (-10000..10000).step(17)

 raise unless n == int_from_words(wordify(n))

end

for n in 0...20

 raise unless 13**n == int_from_words(wordify(13**n))

end

puts "##\n## These tests show <==> for a successful round trip, otherwise <??>\n##" for n in [0, -3, 5, -7, 11, -13, 17, -19, 23, -29]

 txt = wordify(n)
 num = int_from_words(txt)
 puts '%+4i <%s> %s' % [n, n==num ? '==' : '??', txt]

end puts

n = 201021002001 loop do

 txt = wordify(n)
 num = int_from_words(txt)
 puts '%12i <%s> %s' % [n, n==num ? '==' : '??', txt]
 break if n==0
 n /= -10

end</lang>

Output:
##
## These tests show <==> for a successful round trip, otherwise <??>
##
  +0 <==> zero
  -3 <==> negative three
  +5 <==> five
  -7 <==> negative seven
 +11 <==> eleven
 -13 <==> negative thirteen
 +17 <==> seventeen
 -19 <==> negative nineteen
 +23 <==> twenty-three
 -29 <==> negative twenty-nine

201021002001 <==> two hundred and one billion, twenty-one million, two thousand, one
-20102100201 <==> negative twenty billion, one hundred and two million, one hundred thousand, two hundred and one
  2010210020 <==> two billion, ten million, two hundred and ten thousand, twenty
  -201021002 <==> negative two hundred and one million, twenty-one thousand, two
    20102100 <==> twenty million, one hundred and two thousand, one hundred
    -2010210 <==> negative two million, ten thousand, two hundred and ten
      201021 <==> two hundred and one thousand, twenty-one
      -20103 <==> negative twenty thousand, one hundred and three
        2010 <==> two thousand, ten
        -201 <==> negative two hundred and one
          20 <==> twenty
          -2 <==> negative two
           0 <==> zero

Sidef

Translation of: Perl

<lang ruby>func names_to_number(str) {

   static nums = Hash.new(
          zero => 0,             one => 1,             two => 2,
         three => 3,            four => 4,            five => 5,
           six => 6,           seven => 7,           eight => 8,
          nine => 9,             ten => 10,         eleven => 11,
        twelve => 12,       thirteen => 13,       fourteen => 14,
       fifteen => 15,        sixteen => 16,      seventeen => 17,
      eighteen => 18,       nineteen => 19,         twenty => 20,
        thirty => 30,          forty => 40,          fifty => 50,
         sixty => 60,        seventy => 70,         eighty => 80,
        ninety => 90,        hundred => 1e2,      thousand => 1e3,
       million => 1e6,       billion => 1e9,      trillion => 1e12,
   quadrillion => 1e15,  quintillion => 1e18,
   );
   # Groupings for thousands, millions, ..., quintillions
   static groups = /\d{4}|\d{7}|\d{10}|\d{13}|\d{16}|\d{19}/;
   # Numeral
   static num = /\d+/;
   str.trim!;                      # remove leading and trailing whitespace
   str.gsub!('-', ' ');            # convert hyphens to spaces
   str.words!.join!(' ');          # remove duplicate whitespace, convert ws to space
   str.lc!;                        # convert to lower case
   # tokenize sentence boundaries
   str.gsub!(/([.?!]) /, {|a| ' ' + a + "\n"});
   str.gsub!(/([.?!])$/, {|a| ' ' + a + "\n"});
   # tokenize other punctuation and symbols
   str.gsub!(/\$(.)/,           {|a| "$ #{a}" });       # prefix
   str.gsub!(/(.)([;:%,])/, {|a,b| "#{a} #{b}"});     # suffix
   nums.each { |key, value| str.gsub!(Regex.new('\b' + key + '\b'), value) };
   str.gsub!(/(\d) , (\d)/,   {|a,b| a + ' ' + b});
   str.gsub!(/(\d) and (\d)/, {|a,b| a + ' ' + b});
   static regex = [
       Regex.new('\b(\d) 100 (\d\d) (\d) (' + groups + ')\b'),
       Regex.new('\b(\d) 100 (\d\d) (' + groups + ')\b'),
       Regex.new('\b(\d) 100 (\d) (' + groups + ')\b'),
       Regex.new('\b(\d) 100 (' + groups + ')\b'),
       Regex.new('\b100 (\d\d) (\d) (' + groups + ')\b'),
       Regex.new('\b100 (\d\d) (' + groups + ')\b'),
       Regex.new('\b100 (\d) (' + groups + ')\b'),
       Regex.new('\b100 (' + groups + ')\b'),
       Regex.new('\b(\d\d) (\d) (' + groups + ')\b'),
       Regex.new('\b(\d{1,2}) (' + groups + ')\b'),
       Regex.new('((?:' + num + ' )*' + num + ')'),
   ];
   str.gsub!(regex[0], {|a,b,c,d| (a.to_i*100 + b.to_i + c.to_i) * d.to_i });
   str.gsub!(regex[1], {|a,b,c|   (a.to_i*100 + b.to_i) * c.to_i });
   str.gsub!(regex[2], {|a,b,c|   (a.to_i*100 + b.to_i) * c.to_i });
   str.gsub!(regex[3], {|a,b|     (a.to_i * b.to_i * 100) });
   str.gsub!(regex[4], {|a,b,c|   (100 + a.to_i + b.to_i) * c.to_i });
   str.gsub!(regex[5], {|a,b|     (100 + a.to_i) * b.to_i });
   str.gsub!(regex[6], {|a,b|     (100 + a.to_i) * b.to_i });
   str.gsub!(regex[7], {|a|       (a.to_i * 100) });
   str.gsub!(regex[8], {|a,b,c|   (a.to_i + b.to_i) * c.to_i });
   str.gsub!(regex[9], {|a,b|     (a.to_i * b.to_i) });
   str.gsub!(/\b(\d\d) (\d) 100\b/, {|a,b| (a.to_i + b.to_i) * 100});
   str.gsub!(/\b(\d{1,2}) 100\b/,   {|a|   (a.to_i * 100) });
   str.gsub!(/\b(\d{2}) (\d{2})\b/, {|a,b| (a.to_i * 100) + b.to_i});
   str.gsub!(regex[10], {|a| a.split(' ').map{.to_i}.sum });

}</lang>

Usage: <lang ruby>ARGF.each { |line|

   say "#{line.chomp.dump} --> #{names_to_number(line).dump}";

}</lang>

Sample:

$ sidef names2nums.sf input.txt
"Seventy two dollars" --> "72 dollars"
"One Hundred and One Dalmatians" --> "101 dalmatians"
"Two Thousand and One: A Space Odyssey" --> "2001 : a space odyssey"
"Twenty Thirteen" --> "2013"
"Nineteen Eighty-Four" --> "1984"
"one thousand, five hundred and one" --> "1501"
"three hundred and ten" --> "310"
"ninety-nine" --> "99"
"ninety nine thousand nine hundred ninety nine" --> "99999"
"five hundred and twelve thousand, six hundred and nine" --> "512609"
"two billion, one hundred" --> "2000000100"

Tcl

Works with: Tcl version 8.6

<lang tcl>package require Tcl 8.6 proc name2num name {

   set words [regexp -all -inline {[a-z]+} [string tolower $name]]
   set tokens {

"zero" 0 "one" 1 "two" 2 "three" 3 "four" 4 "five" 5 "six" 6 "seven" 7 "eight" 8 "nine" 9 "ten" 10 "eleven" 11 "twelve" 12 "thirteen" 13 "fourteen" 14 "fifteen" 15 "sixteen" 16 "seventeen" 17 "eighteen" 18 "nineteen" 19 "twenty" 20 "thirty" 30 "forty" 40 "fifty" 50 "sixty" 60 "seventy" 70 "eighty" 80 "ninety" 90 "hundred" 100 "thousand" 1000 "million" 1000000 "billion" 1000000000 "trillion" 1000000000000 "quadrillion" 1000000000000000 "qintillion" 1000000000000000000

   }
   set values {}
   set groups {}
   set previous -inf
   set sign 1
   foreach word $words {

if {[dict exists $tokens $word]} { set value [dict get $tokens $word] if {$value < $previous} { # Check if we have to propagate backwards the "large" terms if {[set mult [lindex $values end]] > 99} { for {set i [llength $groups]} {[incr i -1] >= 0} {} { if {[lindex $groups $i end] >= $mult} { break } lset groups $i end+1 $mult } } lappend groups $values set values {} } elseif {$value < 100 && $previous < 100 && $previous >= 0} { # Special case: dates lappend groups [lappend values 100] set values {} } lappend values $value set previous $value } elseif {$word eq "minus"} { set sign -1 }

   }
   lappend groups $values
   set groups [lmap prodgroup $groups {tcl::mathop::* {*}$prodgroup}]
   # Special case: dates
   if {[llength $groups] == 2} {

if {[lmap g $groups {expr {$g < 100 && $g >= 10}}] eq {1 1}} { lset groups 0 [expr {[lindex $groups 0] * 100}] }

   }
   return [expr {$sign * [tcl::mathop::+ {*}$groups]}]

}</lang> Demonstrating/testing (based on Perl code's samples): <lang tcl>set samples {

   "Seventy-two dollars"
   "Seventy two dollars"
   "One Hundred and One Dalmatians"
   "A Hundred and One Dalmatians"
   "One Hundred One Dalmatians"
   "Hundred and One Dalmatians"
   "One Thousand and One Nights"
   "Two Thousand and One: A Space Odyssey"
   "Twenty Thirteen"
   "Nineteen Eighty-Four"
   "four billion, two hundred ninety-four million, nine hundred sixty-seven thousand, two hundred ninety five"
   "Nine quadrillion, seven trillion, one hundred ninety-nine billion, two hundred fifty-four million, seven hundred forty thousand, nine hundred ninety two"
   "Nine Hundred Ninety-Nine"
   "One Thousand One Hundred Eleven"
   "Eleven Hundred Eleven"
   "Eight Thousand Eight Hundred Eighty-Eight"
   "Eighty-Eight Hundred Eighty-Eight"
   "Seven Million Seven Hundred Seventy-Seven Thousand Seven Hundred Seventy-Seven"
   "Ninety-Nine Trillion Nine Hundred Ninety-Nine Billion Nine Hundred Ninety-Nine Million Nine Hundred Ninety-Nine Thousand Nine Hundred Ninety-Nine"
   "ninety-nine"
   "three hundred"
   "three hundred and ten"
   "one thousand, five hundred and one"
   "twelve thousand, six hundred and nine"
   "five hundred and twelve thousand, six hundred and nine"
   "forty-three million, one hundred and twelve thousand, six hundred and nine"
   "two billion, one hundred"
   "zero"
   "eight"
   "one hundred"
   "one hundred twenty three"
   "one thousand one"
   "ninety nine thousand nine hundred ninety nine"
   "one hundred thousand"
   "nine billion one hundred twenty three million four hundred fifty six thousand seven hundred eighty nine"
   "one hundred eleven billion one hundred eleven"
   "minus fifty six"

} foreach s $samples {

   puts "$s => [name2num $s]"

}</lang>

Output:
Seventy-two dollars => 72
Seventy two dollars => 72
One Hundred and One Dalmatians => 101
A Hundred and One Dalmatians => 101
One Hundred One Dalmatians => 101
Hundred and One Dalmatians => 101
One Thousand and One Nights => 1001
Two Thousand and One: A Space Odyssey => 2001
Twenty Thirteen => 2013
Nineteen Eighty-Four => 1984
four billion, two hundred ninety-four million, nine hundred sixty-seven thousand, two hundred ninety five => 4294967295
Nine quadrillion, seven trillion, one hundred ninety-nine billion, two hundred fifty-four million, seven hundred forty thousand, nine hundred ninety two => 9007199254740992
Nine Hundred Ninety-Nine => 999
One Thousand One Hundred Eleven => 1111
Eleven Hundred Eleven => 1111
Eight Thousand Eight Hundred Eighty-Eight => 8888
Eighty-Eight Hundred Eighty-Eight => 8888
Seven Million Seven Hundred Seventy-Seven Thousand Seven Hundred Seventy-Seven => 7777777
Ninety-Nine Trillion Nine Hundred Ninety-Nine Billion Nine Hundred Ninety-Nine Million Nine Hundred Ninety-Nine Thousand Nine Hundred Ninety-Nine => 99999999999999
ninety-nine => 99
three hundred => 300
three hundred and ten => 310
one thousand, five hundred and one => 1501
twelve thousand, six hundred and nine => 12609
five hundred and twelve thousand, six hundred and nine => 512609
forty-three million, one hundred and twelve thousand, six hundred and nine => 43112609
two billion, one hundred => 2000000100
zero => 0
eight => 8
one hundred => 100
one hundred twenty three => 123
one thousand one => 1001
ninety nine thousand nine hundred ninety nine => 99999
one hundred thousand => 100000
nine billion one hundred twenty three million four hundred fifty six thousand seven hundred eighty nine => 9123456789
one hundred eleven billion one hundred eleven => 111000000111
minus fifty six => -56

Wren

Translation of: Kotlin
Library: Wren-str
Library: Wren-pattern
Library: Wren-fmt

Wren's built in Num type can only deal accurately with integers up to 16 digits long (plus or minus 2 ^ 53) so without resorting to BigInt (which would be overkill here) we can only deal with numbers up to nine quadrillion or so. <lang ecmascript>import "/str" for Str import "/pattern" for Pattern import "/fmt" for Fmt var names = {

   "one": 1,
   "two": 2,
   "three": 3,
   "four": 4,
   "five": 5,
   "six": 6,
   "seven": 7,
   "eight": 8,
   "nine": 9,
   "ten": 10,
   "eleven": 11,
   "twelve": 12,
   "thirteen": 13,
   "fourteen": 14,
   "fifteen": 15,
   "sixteen": 16,
   "seventeen": 17,
   "eighteen": 18,
   "nineteen": 19,
   "twenty": 20,
   "thirty": 30,
   "forty": 40,
   "fifty": 50,
   "sixty": 60,
   "seventy": 70,
   "eighty": 80,
   "ninety": 90,
   "hundred": 100,
   "thousand": 1e3,
   "million": 1e6,
   "billion": 1e9,
   "trillion": 1e12,
   "quadrillion": 1e15

}

var zeros = ["zero", "nought", "nil", "none", "nothing"]

var seps = Pattern.new("[,|-| and | ]")

var nameToNum = Fn.new { |name|

   var text = Str.lower(name.trim())
   var isNegative = text.startsWith("minus ")
   if (isNegative) text = text[6..-1]
   if (text.startsWith("a ")) text = "one" + text[1..-1]
   var words = seps.splitAll(text).where { |w| w != "" }.toList
   var size = words.count
   if (size == 1 && zeros.contains(words[0])) return 0
   var multiplier = 1
   var lastNum = 0
   var sum = 0
   for (i in size-1..0) {
       var num = names[words[i]]
       if (!num) Fiber.abort("'%(words[i])' is not a valid number")
       if (num == lastNum) Fiber.abort("'%(name)' is not a well formed numeric string")
       if (num >= 1000) {
           if (lastNum >= 100) {
               Fiber.abort("'%(name)' is not a well formed numeric string")
           }
           multiplier = num
           if (i == 0) sum = sum + multiplier
       } else if (num >= 100) {
           multiplier = multiplier * 100
           if (i == 0) sum = sum + multiplier
       } else if (num >= 20) {
           if (lastNum >= 10 && lastNum <= 90) {
               Fiber.abort("'%(name)' is not a well formed numeric string")
           }
           sum = sum + num*multiplier
       } else {
            if (lastNum >= 1 && lastNum <= 90) {
               Fiber.abort("'%(name)' is not a well formed numeric string")
           }
           sum = sum + num*multiplier
       }
       lastNum = num
   }
   return (isNegative) ? -sum : sum

}

var tests = [

   "none",
   "one",
   "twenty-five",
   "minus one hundred and seventeen",
   "hundred and fifty-six",
   "minus two thousand two",
   "nine thousand, seven hundred, one",
   "minus six hundred and twenty six thousand, eight hundred and fourteen",
   "four million, seven hundred thousand, three hundred and eighty-six",
   "fifty-one billion, two hundred and fifty-two million, seventeen thousand, one hundred eighty-four",
   "two hundred and one billion, twenty-one million, two thousand and one",
   "minus three hundred trillion, nine million, four hundred and one thousand and thirty-one",
   "one quadrillion and one",
   "minus nine quadrillion, one hundred thirty-seven"

] for (name in tests) Fmt.print("$17d = $s", nameToNum.call(name), name)</lang>

Output:
                0 = none
                1 = one
               25 = twenty-five
             -117 = minus one hundred and seventeen
              156 = hundred and fifty-six
            -2002 = minus two thousand two
             9701 = nine thousand, seven hundred, one
          -626814 = minus six hundred and twenty six thousand, eight hundred and fourteen
          4700386 = four million, seven hundred thousand, three hundred and eighty-six
      51252017184 = fifty-one billion, two hundred and fifty-two million, seventeen thousand, one hundred eighty-four
     201021002001 = two hundred and one billion, twenty-one million, two thousand and one
 -300000009401031 = minus three hundred trillion, nine million, four hundred and one thousand and thirty-one
 1000000000000001 = one quadrillion and one
-9000000000000137 = minus nine quadrillion, one hundred thirty-seven

zkl

<lang zkl>var names=T("zero","one","two","three","four","five","six","seven","eight", "nine","ten","eleven","twelve","thirteen","fourteen","fifteen", "sixteen","seventeen","eighteen","nineteen","twenty", "thirty","forty","fifty","sixty","seventy","eighty","ninety", "hundred","thousand","million","billion", "trillion") .zip([0..20].chain([30..90,10]).walk().append( 100,1000,1000000,1000000000,1000000000000)) .toDictionary();

fcn stringToNumber(s){

  s=s.toLower().replace(",","").replace(" and "," ").replace("-"," ");
  words,minus,total,hund,prev := s.split(), 1,0,0,0;
  if(not words) return(0);
  if(words[0]=="minus"){ minus=-1; words=words[1,*]; }
  foreach w in (words){
     n:=names.find(w);
     if(Void==n) throw(Exception.ValueError("I don't know "+w));
     if(n<100){
     	 dn,dp := n.numDigits,prev.numDigits;  // 0,1,2 and 0,1,2,3,...

if(dp<3) if((dn==dp==1) or dn==0 or dp==0) hund*=10; else if(dn==2) hund*=100; hund+=n;

     }
     else if(n==100) hund*=n;
     else{ total+=hund*n; hund=0; }
     prev=n;
  }
  minus*(total + hund)  

}</lang> <lang zkl>foreach s in (T("eighty-five thousand and one ",

    " one hundred and fifty-five thousand and nineteen",
    "one thousand,   nine hundred and eighty-four","Nineteen Eighty-Four", 
    "six thousand Nineteen Eighty-Four",
    "","zero","zero zero one","one zero","one zero two","one one three",
    "ninety one","one ninety","ninety ninety",
    "minus four million, five hundred and forty-seven thousand",
    "six million, seven hundred and sixty-six thousand and twenty-seven")){
  println("\"%s\" is %,d".fmt(s,stringToNumber(s)));

}</lang>

Output:
"eighty-five thousand and one " is 85,001
" one hundred and fifty-five thousand and nineteen" is 155,019
"one thousand,   nine hundred and eighty-four" is 1,984
"Nineteen Eighty-Four" is 1,984
"six thousand Nineteen Eighty-Four" is 7,984
"" is 0
"zero" is 0
"zero zero one" is 1
"one zero" is 10
"one zero two" is 102
"one one three" is 113
"ninety one" is 91
"one ninety" is 190
"ninety ninety" is 9,090
"minus four million, five hundred and forty-seven thousand" is -4,547,000
"six million, seven hundred and sixty-six thousand and twenty-seven" is 6,766,027