Mat Posted July 14, 2010 Share Posted July 14, 2010 (edited) After some confusion in general help and support I ended up writing this for absolutely no reason. Never mind, in the toolbox it goes.Uses the short scale (used by the USA - billion = thousand million)Huge numbers can be converted (up to 134217727 digits before the decimal point has been tested... After the decimal point depends on how much memory you have available)Uses number names up to vigintillionNegative numbers and decimals allowed.Does the 'and' after the big numbers.Now includes reversal (NumFromWord)expandcollapse popupFunc NumFromWord($sWord) Local $sDigits = "zero|one|two|three|four|five|six|seven|eight|nine" Local $sTeens = "eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen" Local $sTens = "ten|twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety" Local $sBig = "thousand|million|billion|trillion|quadrillion|quintillion|sextillion|septillion|octillion|nonillion|" & _ "decillion|undecillion|duodecillion|tredecillion|quattuordecillion|quindecillion|sexdecillion|septendecillion|octodecillion|novemdecillion|vigintillion" Local $asDigits = StringSplit($sDigits, "|", 2) Local $asTeens = StringSplit($sTeens, "|", 2) Local $asTens = StringSplit($sTens, "|", 2) Local $asBig = StringSplit($sBig, "|", 2) Local $sRet = "" Local $iTemp[3] = [0, 0, 0] Local $aWords ; check... If Not StringRegExp($sWord, "^(minus\s+)?((((" & $sTens & ")\s+)?(" & $sDigits & ")|(" & $sTeens & ")|(" & $sTens & "))\s+(hundred|" & $sBig & ")(\s+and)?(\s+|\z))*(((" & $sTens & ")\s+)?(" & $sDigits & ")?|(" & $sTeens & ")|(" & $sTens & "))(\s+point(\s+(" & $sDigits & "))+)?$") Then _ Return SetError(1) $sWord = StringReplace($sWord, " and", "") For $i = 0 To 8 $sWord = StringReplace($sWord, $asTeens[$i], "ten " & $asDigits[$i + 1]) Next $aWords = StringSplit($sWord, " ") If StringInStr($sWord, " point ") Then Do For $n = 0 To UBound($asDigits) - 1 If $asDigits[$n] = $aWords[$aWords[0]] Then $sRet = $n & $sRet ExitLoop EndIf Next $aWords[0] -= 1 Until $aWords[$aWords[0]] <> "point" $sRet = "." & $sRet If $aWords[$aWords[0]] = "zero" Then $sRet = "0" & $sRet EndIf For $i = $aWords[0] To 1 Step -1 If $i = 1 And $aWords[1] = "minus" Then $sRet = "-" & $sRet ExitLoop EndIf If StringInStr("|" & $sDigits & "|", "|" & $aWords[$i] & "|") Then ; Digit If $iTemp[0] <> 0 Then Return SetError(2, $i, "") ; Invalid word: @extended, expected large identifier not digit. For $n = 0 To UBound($asDigits) - 1 If $asDigits[$n] = $aWords[$i] Then $iTemp[0] = $n ExitLoop EndIf Next ElseIf StringInStr("|" & $sTens & "|", "|" & $aWords[$i] & "|") Then ; Tens If $iTemp[1] <> 0 Then Return SetError(3, $i, "") ; Invalid word: @extended, expected large identifier not ten. For $n = 0 To UBound($asTens) - 1 If $asTens[$n] = $aWords[$i] Then $iTemp[1] = $n + 1 ExitLoop EndIf Next ElseIf $aWords[$i] = "hundred" Then ; hundred If $iTemp[2] <> 0 Then Return SetError(4, $i, "") ; Invalid word: @extended, expected large identifier not hundred. For $n = 0 To UBound($asDigits) - 1 If $asDigits[$n] = $aWords[$i - 1] Then $iTemp[2] = $n $i -= 1 ExitLoop EndIf Next ElseIf StringInStr("|" & $sBig & "|", "|" & $aWords[$i] & "|") Then ; BIG $sRet = $iTemp[2] & $iTemp[1] & $iTemp[0] & $sRet $iTemp[0] = 0 $iTemp[1] = 0 $iTemp[2] = 0 Else Return SetError(4, $i, "") ; Invalid word: @extended, word not recognized. EndIf Next $sRet = $iTemp[2] & $iTemp[1] & $iTemp[0] & $sRet ; No leading 0's While StringLeft($sRet, 1) = "0" And StringLeft($sRet, 2) <> "0." $sRet = StringTrimLeft($sRet, 1) WEnd ; No trailing 0's if decimal If StringInStr($sRet, ".") Then While StringRight($sRet, 1) = "0" $sRet = StringTrimRight($sRet, 1) WEnd If StringRight($sRet, 1) = "." Then $sRet = StringTrimRight($sRet, 1) EndIf Return $sRet EndFunc ;==>NumFromWord Func NumToWord($iNum) $iNum = String($iNum) $iNum = StringStripWS($iNum, 8) If Not StringRegExp($iNum, "^-?\d+?(\.\d+)?$") Then Return SetError(2, 0, "") If $iNum = "0" Then Return "zero" Local $asDigits[10] = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"] Local $asTeens[9] = ["eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"] Local $asTens[9] = ["ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"] Local $asBig[21] = ["thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion", "octillion", "nonillion", _ "decillion", "undecillion", "duodecillion", "tredecillion", "quattuordecillion", "quindecillion", "sexdecillion", "septendecillion", "octodecillion", "novemdecillion", "vigintillion"] ; No leading 0's While StringLeft($iNum, 1) = "0" And StringLeft($iNum, 2) <> "0." $iNum = StringTrimLeft($iNum, 1) WEnd ; No trailing 0's if decimal If StringInStr($iNum, ".") Then While StringRight($iNum, 1) = "0" $iNum = StringTrimRight($iNum, 1) WEnd If StringRight($iNum, 1) = "." Then $iNum = StringTrimRight($iNum, 1) EndIf Local $iTemp Local $iLen Local $sRet = "" Local $nDec = "" ; Do decimal places later If StringInStr($iNum, ".") Then $nDec = StringMid($iNum, StringInStr($iNum, ".") + 1) $iNum = StringLeft($iNum, StringInStr($iNum, ".") - 1) EndIf ; Check negative If StringLeft($iNum, 1) = "-" Then $iNum = StringTrimLeft($iNum, 1) $sRet &= "minus " EndIf ; Very big numbers For $i = 21 To 1 Step -1 If StringLen($iNum) > $i * 3 Then $iLen = Mod(StringLen($iNum), 3) If $iLen = 0 Then $iLen = 3 $iTemp = StringLeft($iNum, $iLen) $iNum = StringTrimLeft($iNum, $iLen) $iTemp = NumToWord($iTemp) If $iTemp = "" Or $iTemp = "0" Then ContinueLoop If Not @error Then $sRet &= $iTemp & " " & $asBig[$i - 1] & " " EndIf Next ; hundreds If StringLen($iNum) >= 3 Then $iTemp = StringLeft($iNum, 1) $iNum = StringTrimLeft($iNum, 1) If $iTemp <> "0" Then $sRet &= $asDigits[Int($iTemp)] & " hundred " If $iNum <> "00" Then $sRet &= "and " EndIf If StringLen($iNum) = 2 And StringLeft($iNum, 1) = "1" And StringRight($iNum, 1) <> "0" Then $iTemp = StringRight($iNum, 1) $sRet &= $asTeens[Int($iTemp) - 1] & " " $iNum = "" Else ; Tens If StringLen($iNum) = 2 Then $iTemp = StringLeft($iNum, 1) $iNum = StringTrimLeft($iNum, 1) If $iTemp <> "0" Then $sRet &= $asTens[Int($iTemp) - 1] & " " EndIf ; Digits If StringLen($iNum) = 1 Then If $iNum <> "0" Then $sRet &= $asDigits[Int($iNum)] & " " $iNum = "" EndIf EndIf If $nDec <> "" Then If $sRet = "" Or $sRet = "minus " Then $sRet &= "zero " $sRet &= "point " Do $iTemp = StringLeft($nDec, 1) $nDec = StringTrimLeft($nDec, 1) $sRet &= $asDigits[Int($iTemp)] & " " Until $nDec = "" EndIf $sRet = StringTrimRight($sRet, 1) Return $sRet EndFunc ;==>NumToWordMat Edited July 15, 2010 by Mat Guy_ 1 AutoIt Project Listing Link to comment Share on other sites More sharing options...
MrCreatoR Posted July 14, 2010 Share Posted July 14, 2010 Nice! What about make it work in reverse mode, i mean convert Words to numbers? Spoiler Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1 AutoIt Russian Community My Work... Spoiler Projects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize ProgramUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF Examples: ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating ) * === My topics === * ================================================== ================================================== AutoIt is simple, subtle, elegant. © AutoIt Team Link to comment Share on other sites More sharing options...
Mat Posted July 15, 2010 Author Share Posted July 15, 2010 Nice!What about make it work in reverse mode, i mean convert Words to numbers?I knew someone would ask that I'm working on it. AutoIt Project Listing Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted July 15, 2010 Moderators Share Posted July 15, 2010 Mat, It took a bit of finding, but you might find some of the posts in this thread of interest. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
James Posted July 15, 2010 Share Posted July 15, 2010 (edited) Mat,Well done for solving Problem 17!expandcollapse popupGlobal $strWord Global $strFin For $i = 1 To 1000 $strWord = StringStripWS(NumToWord($i), 8) ConsoleWrite($strWord & @CRLF) $strFin += StringLen($strWord) Next ConsoleWrite($strFin & @CRLF) Func NumToWord($iNum) $iNum = String($iNum) $iNum = StringStripWS($iNum, 8) If Not StringRegExp($iNum, "^-?\d+?(\.\d+)?$") Then Return SetError(2, 0, "") If $iNum = "0" Then Return "zero" Local $asDigits[10] = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"] Local $asTeens[9] = ["eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"] Local $asTens[9] = ["ten", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"] Local $asBig[21] = ["thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "sextillion", "septillion", "octillion", "nonillion", _ "decillion", "undecillion", "duodecillion", "tredecillion", "quattuordecillion", "quindecillion", "sexdecillion", "septendecillion", "octodecillion", "novemdecillion", "vigintillion"] ; No leading 0's While StringLeft($iNum, 1) = "0" And StringLeft($iNum, 2) <> "0." $iNum = StringTrimLeft($iNum, 1) WEnd ; No trailing 0's if decimal If StringInStr($iNum, ".") Then While StringRight($iNum, 1) = "0" $iNum = StringTrimRight($iNum, 1) WEnd If StringRight($iNum, 1) = "." Then $iNum = StringTrimRight($iNum, 1) EndIf Local $iTemp Local $iLen Local $sRet = "" Local $nDec = "" ; Do decimal places later If StringInStr($iNum, ".") Then $nDec = StringMid($iNum, StringInStr($iNum, ".") + 1) $iNum = StringLeft($iNum, StringInStr($iNum, ".") - 1) EndIf ; Check negative If StringLeft($iNum, 1) = "-" Then $iNum = StringTrimLeft($iNum, 1) $sRet &= "minus " EndIf ; Very big numbers For $i = 21 To 1 Step -1 If StringLen($iNum) > $i * 3 Then $iLen = Mod(StringLen($iNum), 3) If $iLen = 0 Then $iLen = 3 $iTemp = StringLeft($iNum, $iLen) $iNum = StringTrimLeft($iNum, $iLen) $iTemp = NumToWord($iTemp) If $iTemp = "" Or $iTemp = "0" Then ContinueLoop If Not @error Then $sRet &= $iTemp & " " & $asBig[$i - 1] & " " EndIf Next ; hundreds If StringLen($iNum) >= 3 Then $iTemp = StringLeft($iNum, 1) $iNum = StringTrimLeft($iNum, 1) If $iTemp <> "0" Then $sRet &= $asDigits[Int($iTemp)] & " hundred " If $iNum <> "00" Then $sRet &= "and " EndIf If StringLen($iNum) = 2 And StringLeft($iNum, 1) = "1" And StringRight($iNum, 1) <> "0" Then $iTemp = StringRight($iNum, 1) $sRet &= $asTeens[Int($iTemp) - 1] & " " $iNum = "" Else ; Tens If StringLen($iNum) = 2 Then $iTemp = StringLeft($iNum, 1) $iNum = StringTrimLeft($iNum, 1) If $iTemp <> "0" Then $sRet &= $asTens[Int($iTemp) - 1] & " " EndIf ; Digits If StringLen($iNum) = 1 Then If $iNum <> "0" Then $sRet &= $asDigits[Int($iNum)] & " " $iNum = "" EndIf EndIf If $nDec <> "" Then $sRet &= "point " Do $iTemp = StringLeft($nDec, 1) $nDec = StringTrimLeft($nDec, 1) $sRet &= $asDigits[Int($iTemp)] & " " Until $nDec = "" EndIf $sRet = StringTrimRight($sRet, 1) Return $sRetEndFunc ;==>NumToWordJamesP.S, you could cut out a load of unnecessary code for dealing with bigger numbers $asBig so that it runs even quicker, seeing as the requirement for 17 is 1000. Edited July 15, 2010 by JamesBrooks Blog - Seriously epic web hosting - Twitter - GitHub - Cachet HQ Link to comment Share on other sites More sharing options...
Mat Posted July 15, 2010 Author Share Posted July 15, 2010 It took a bit of finding, but you might find some of the posts in this thread of interest. That's going to be a lot of work as well... How am I going to translate all the words? Well done for solving Problem 17! James P.S, you could cut out a load of unnecessary code for dealing with bigger numbers $asBig so that it runs even quicker, seeing as the requirement for 17 is 1000. I like the big numbers, up to 1000 is easy anyway. I'm working on even bigger numbers (googol etc.). As for the reversal, here's how I think I can make it work... I can check using this pattern: StringRegExp($sWord, "^(minus\s+)?((((" & $sTens & ")\s+)?(" & $sDigits & ")|(" & $sTeens & ")|(" & $sTens & "))\s+(hundred|" & $sBig & ")(\s+and)?(\s+|\z))*(((" & $sTens & ")\s+)?(" & $sDigits & ")?|(" & $sTeens & ")|(" & $sTens & "))(\s+point(\s+(" & $sDigits & "))+)?$") It's then going to go through each word in reverse, storing it in a temporary var, until it reaches a big number. Then it will pad the var to 3 characters and add it to the return string. It should work AutoIt Project Listing Link to comment Share on other sites More sharing options...
czardas Posted July 15, 2010 Share Posted July 15, 2010 (edited) How about number to word to syllables to rhythm? > > > 1117 One thou-sand one hun-dered and se-ven-teen Count 1 2 3 1 2 3 1 2 & 3 Perhaps you could add that one to Project Euler. I'm just joking, but I have a similar conversion problem. From musical chord name to formula. The biggest problem here is that chord nomenclature does not follow consistant rules. This is because chord construction is based on a set of instructions which often lead to erroneous interpretation. Different, and frequently incompatible, systems are used in different styles of music. That makes things quite complicated. Anyway, I'm pretty sure I've solved it by now (at least in theory). It's slightly annoying, though no big deal. Edited July 15, 2010 by czardas operator64 ArrayWorkshop Link to comment Share on other sites More sharing options...
James Posted July 15, 2010 Share Posted July 15, 2010 (edited) Uploaded solution to Google Code P.S we need to edit the old solutions since OnAutoItExit no longer exists. James Edited July 15, 2010 by JamesBrooks Blog - Seriously epic web hosting - Twitter - GitHub - Cachet HQ Link to comment Share on other sites More sharing options...
Spiff59 Posted July 15, 2010 Share Posted July 15, 2010 Mat, It took a bit of finding, but you might find some of the posts in this thread of interest. M23 I knew we'd played with this exact same function over a year ago, and that that thread was out there somewhere, but my searches came up empty! Somehow "locale" as a search string never entered my mind. Good job finding it, M23. I, of course, like the 33-line submission in post #32 of the thread Link to comment Share on other sites More sharing options...
Mat Posted July 15, 2010 Author Share Posted July 15, 2010 Uploaded solution to Google Code P.S we need to edit the old solutions since OnAutoItExit no longer exists.It's been a long time since I even visited that page... Is there not a system for multiple solutions? I thought I built that in. A better solution would be to rewrite the function for speed I knew we'd played with this exact same function over a year ago, and that that thread was out there somewhere, but my searches came up empty! Somehow "locale" as a search string never entered my mind. Good job finding it, M23.I, of course, like the 33-line submission in post #32 of the thread Thats a nice way to do it... not sure if Megakazillion is a dictionary term though The post below yours puts me off doing locales though. AutoIt Project Listing Link to comment Share on other sites More sharing options...
Mat Posted July 15, 2010 Author Share Posted July 15, 2010 NumFromWord now works There was also a bug with 0.* which missed out the zero. AutoIt Project Listing Link to comment Share on other sites More sharing options...
jvanegmond Posted July 19, 2010 Share Posted July 19, 2010 (edited) I was struggling with WordToNum until I added: $sWord = StringLower($sWord) Cool stuff, Mat. Edited July 19, 2010 by Manadar github.com/jvanegmond Link to comment Share on other sites More sharing options...
Mat Posted July 19, 2010 Author Share Posted July 19, 2010 Ah... I will fix it in 6 weeks time AutoIt Project Listing Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now