The string-parsing version of the function now works for arbitrarily-large numbers. master
authorJustin Wind <justin.wind@gmail.com>
Sat, 2 Feb 2013 19:35:49 +0000 (11:35 -0800)
committerJustin Wind <justin.wind@gmail.com>
Sat, 2 Feb 2013 19:35:49 +0000 (11:35 -0800)
Implemention suggested by Stacey.

english-numbers.muf

index dc2c74803235f7a6915f8991c72045692e1d8dcf..ad3f69e42326ec0be6dc5b1d9a5da7587537fdc7 100644 (file)
@@ -6,17 +6,19 @@ $note A simple routine to render a numeric value as english words.
 $libdef english-number
 ( english-numbers.muf
   Dec 11 2012 - v1.000
 $libdef english-number
 ( english-numbers.muf
   Dec 11 2012 - v1.000
+  Feb  2 2012 - v1.001
 
   caveats:
     doesn't handle floats
 
   caveats:
     doesn't handle floats
-    doesn't check for overflow
+    integer variant doesn't check for integer overflow
     doesn't do fancy shortening, like someteen-hundred
 )
 
 $lib-version 1.000
     doesn't do fancy shortening, like someteen-hundred
 )
 
 $lib-version 1.000
-$version 1.000
+$version 1.001
 $author <justin.wind@gmail.com>
 
 $author <justin.wind@gmail.com>
 
+$undef DEBUGGING
 $ifdef DEBUGGING
 ( trim some debug fluff )
 $def D_SAVE prog "D" flag? D_STATE !
 $ifdef DEBUGGING
 ( trim some debug fluff )
 $def D_SAVE prog "D" flag? D_STATE !
@@ -64,6 +66,7 @@ $endif
     "octodecillion" "novemdecillion" "vigintillion" "silmarillion"
   } array_make
   swap array_getitem
     "octodecillion" "novemdecillion" "vigintillion" "silmarillion"
   } array_make
   swap array_getitem
+  dup 0 = if pop "???-illion" then
   D_RESTORE
 ;
 
   D_RESTORE
 ;
 
@@ -148,8 +151,56 @@ $endif
 ;
 public english-number
 
 ;
 public english-number
 
-: mpi
-  atoi english-number
+: strcut-end ( s i -- s s )
+  over strlen swap -
+  dup 0 <= if
+    ( requested more than string has )
+    pop "" swap
+  else
+    strcut
+  then
+;
+
+( deal with number as string )
+( assumes base10 )
+: mpi-english-number ( s -- s )
+  ( atoi english-number exit )
+  0 var! ISNEG
+  "" var! OUT
+  0 var! BIGNESS
+  begin ( s )
+    dup strlen while ( s )
+    3 strcut-end ( s s )
+    atoi ( s i )
+    dup sign 0 < if
+      1 ISNEG !
+      abs
+    then ( s i )
+    english_sub_thousand_ ( s s )
+    BIGNESS @ dup 1 >= if ( s s i )
+      big_numbers_ ( s s s )
+      " " swap strcat ( s s s )
+      strcat ( s s )
+    else
+      pop ( s s )
+    then
+    OUT @ ( s s s )
+    dup strlen if ( s s s )
+      " " swap strcat
+    then ( s s s )
+    strcat ( s s )
+    OUT ! ( s )
+
+    BIGNESS ++ ( s )
+  repeat ( s )
+  pop
+  OUT @
+  dup strlen not if
+    pop zero_
+  then
+  ISNEG @ if
+    "negative " swap strcat
+  then
 ;
 .
 c
 ;
 .
 c