[Home] [Downloads] [Search] [Help/forum]


Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to "verify" your details, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ MUSHclient ➜ Lua ➜ Converting numbers from text and vice-versa

Converting numbers from text and vice-versa

It is now over 60 days since the last post. This thread is closed.     Refresh page


Pages: 1  2  3 4  

Posted by WillFa   USA  (525 posts)  Bio
Date Reply #30 on Thu 18 Mar 2010 03:06 AM (UTC)

Amended on Thu 18 Mar 2010 03:38 AM (UTC) by WillFa

Message
fixed the code. It was an ordering problem. LPEG was matching "six" and then ending at the "ty" in sixty. Fixed the order. Editted code above works with


print(WordtoNum("two trillion four hundred thirty two billion eight hundred seventy six million three hundred forty five thousand nine hundred twenty three")) --> 2432876345923



p.s. did I mention Pub Crawl? ;)

code copied since we're on a new page:


function WordtoNum (str)
	local P, V, Cf, C, Cg, Cc = lpeg.P, lpeg.V, lpeg.Cf, lpeg.C, lpeg.Cg, lpeg.Cc
	lpeg.locale(lpeg)
	local numvalues = {  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 = 10^2,
				thousand = 10^3,
				million = 10^6,
				billion = 10^9,
				trillion = 10^12,
				quadrillion = 10^15,
				--blah blah
				}

	local ndigit = P"twenty" + P"thirty" + P"forty" + P"fifty" + P"sixty" + P"seventy" + P"eighty" + P"ninety" +
			P'hundred' +
			P"ten" + P"eleven" + P"twelve" + P"thirteen" + P"fourteen" + P"fifteen" +
			P"sixteen" + P"seventeen" + P"eighteen" + P"nineteen" +
			P"one" + P"two" + P"three" + P"four" + P"five" + P"six" + P"seven" + P"eight" + P"nine"


	local powers =   P'vigintillion' + P'novemdecillion' + P'octodecillion' + P'septendecillion' +
				P'sexdecillion' + P'quindecillion' + P'quattuordecillion' + P'tredecillion' +
				P'duodecillion' + P'undecillion' + P'decillion' + P'nonillion' + P'octillion' +
				P'septillion' + P'sextillion' + P'quintillion' + P'quadrillion' + P'trillion' +
				P'billion' + P'million' + P'thousand'

	local function SumVals (seed, ...)
		local cypher = {...}
		local tmp = 0

		for x = 1, #cypher do
			if numvalues[cypher[x]] == 100 then
				if tmp == 0 then
					tmp = 100
				else
					tmp = tmp * 100
				end
			elseif powers:match(cypher[x] or "") then
				tmp = tmp * numvalues[cypher[x]]
			else
				tmp = tmp + numvalues[cypher[x]]
			end
		end
		return seed + tmp
	end

	local cypher = Cg( (C(ndigit) * lpeg.space^-1)^1 * ((C(powers) * lpeg.space^-1) + P(0)) )
	local number = Cf(Cc(0) * cypher^1, SumVals)

	return number:match(str)
end

Top

Posted by Nick Gammon   Australia  (23,046 posts)  Bio   Forum Administrator
Date Reply #31 on Thu 18 Mar 2010 03:15 AM (UTC)
Message
Is that the latest code? I get:


[string "Immediate"]:41: bad argument #1 to 'match' (string expected, got nil)
stack traceback:
	[C]: in function 'match'
	[string "Immediate"]:41: in function <[string "Immediate"]:30>
	[C]: in function 'match'
	[string "Immediate"]:53: in function 'WordtoNum'
	[string "Immediate"]:56: in main chunk


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by WillFa   USA  (525 posts)  Bio
Date Reply #32 on Thu 18 Mar 2010 03:19 AM (UTC)

Amended on Thu 18 Mar 2010 03:22 AM (UTC) by WillFa

Message
oops, add or "" to the powers:match line.

editted above.

I think; what's the string you tested?

the other thing is the numvalues table doesn't contain all the powers of 10 for stuff like duodecaooberzillion.
Top

Posted by Nick Gammon   Australia  (23,046 posts)  Bio   Forum Administrator
Date Reply #33 on Thu 18 Mar 2010 03:21 AM (UTC)
Message
Tiopon said:

I just put zero at the top of the listed numbers, above one... so the top section looks like:
...
and that seems to work properly for those cases... any possible caveats on that?


With that in it accepts "zero", and also constructs like "zero thousand", "zero hundred and twenty two" or "five hundred and zero" which I suppose is OK. It isn't wrong, it just looks strange.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,046 posts)  Bio   Forum Administrator
Date Reply #34 on Thu 18 Mar 2010 03:23 AM (UTC)
Message
WillFa said:

oops, add or "" to the powers:match line.

editted above.

I think; what's the string you tested?


"Your" number:


print(WordtoNum("two trillion four hundred thirty two billion eight hundred seventy six million three hundred forty five thousand nine hundred twenty three")) --> 2432876345923


Still doing it:


[string "Immediate"]:44: attempt to perform arithmetic on field '?' (a nil value)
stack traceback:
	[string "Immediate"]:44: in function <[string "Immediate"]:30>
	[C]: in function 'match'
	[string "Immediate"]:53: in function 'WordtoNum'
	[string "Immediate"]:57: in main chunk


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Twisol   USA  (2,257 posts)  Bio
Date Reply #35 on Thu 18 Mar 2010 03:23 AM (UTC)
Message
This is arguably a good place to use the "be liberal in what you receive, and conservative in what you emit" philosophy. Accepting "zero" was simple to add (seemingly), and doesn't hurt the output.

Bonus points for converting "the answer to life, the universe, and everything" to 42.

'Soludra' on Achaea

Blog: http://jonathan.com/
GitHub: http://github.com/Twisol
Top

Posted by Nick Gammon   Australia  (23,046 posts)  Bio   Forum Administrator
Date Reply #36 on Thu 18 Mar 2010 03:26 AM (UTC)
Message
Thank you Twisol. That is a number that is never far from the front of my mind. :P

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by WillFa   USA  (525 posts)  Bio
Date Reply #37 on Thu 18 Mar 2010 03:28 AM (UTC)

Amended on Thu 18 Mar 2010 03:29 AM (UTC) by WillFa

Message
Edit on this page is correct... I changed my for counter from i to x so I wouldn't have to deal with escaping the brackets in the code, but actually forgot to change the for line...

for i=...
   cypher[x]


silly goof.
Top

Posted by Nick Gammon   Australia  (23,046 posts)  Bio   Forum Administrator
Date Reply #38 on Thu 18 Mar 2010 03:29 AM (UTC)
Message
Willfa, if you don't work the bc library into your solution, it is eventually going to give inaccurate results. I suppose those results will be acceptable if they are going to be converted to a "double" anyway, but why not let the caller do that?

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by WillFa   USA  (525 posts)  Bio
Date Reply #39 on Thu 18 Mar 2010 03:33 AM (UTC)

Amended on Thu 18 Mar 2010 03:34 AM (UTC) by WillFa

Message
Nick Gammon said:

Willfa, if you don't work the bc library into your solution, it is eventually going to give inaccurate results. I suppose those results will be acceptable if they are going to be converted to a "double" anyway, but why not let the caller do that?


that can/should be done in the numvalues table, right? at the moment, it'll parse "five quintillion" but there's no corresponding quintillion = 10^18 in the numvalues table (so the function will error)...

quintillion = bc.number(10^18)
(etc) would solve the issue, right?
Top

Posted by Nick Gammon   Australia  (23,046 posts)  Bio   Forum Administrator
Date Reply #40 on Thu 18 Mar 2010 03:35 AM (UTC)
Message


print(WordtoNum("seven billion nine hundred seventeen million seven hundred sixty one thousand six hundred fifty eight"))

--> 7000000907


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,046 posts)  Bio   Forum Administrator
Date Reply #41 on Thu 18 Mar 2010 03:36 AM (UTC)
Message
WillFa said:


quintillion = bc.number(10^18)
(etc) would solve the issue, right?


Quite possibly in principle, however you probably need to do all the arithmetic in bignums, or you get type conversion problems.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by WillFa   USA  (525 posts)  Bio
Date Reply #42 on Thu 18 Mar 2010 03:39 AM (UTC)

Amended on Thu 18 Mar 2010 03:40 AM (UTC) by WillFa

Message
Nick Gammon said:



print(WordtoNum("seven billion nine hundred seventeen million seven hundred sixty one thousand six hundred fifty eight"))

--> 7000000907




Fixed. Same "seven" .. "ty", "seven" .. "teen" problem as before.
Top

Posted by Nick Gammon   Australia  (23,046 posts)  Bio   Forum Administrator
Date Reply #43 on Thu 18 Mar 2010 03:41 AM (UTC)
Message
Try my test bed:


print (string.rep ("-", 75))

for i = 1, 5000 do
  local s = ""
  for i = 1, math.floor (MtRand () * 10 + 1) do
    s = s .. math.floor (MtRand () * 10)
  end -- for
  
  print ("Converting: '" .. s .. "'")
  local words = assert (convert_numbers_to_words (s))
  print ("Result =", words)

  n2 = WordtoNum (words)
  print ("LPEG result was:", n2)

  assert (tostring (n2) == string.gsub (s, "^0+", ""), "LPEG conversion failed!")
end -- for



For example:


Converting: '2516464739'
Result = two billion five hundred sixteen million four hundred sixty four thousand seven hundred thirty nine
LPEG result was: 2000000506

or

Converting: '883743219'
Result = eight hundred eighty three million seven hundred forty three thousand two hundred nineteen
LPEG result was: 883743209



- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by WillFa   USA  (525 posts)  Bio
Date Reply #44 on Thu 18 Mar 2010 03:49 AM (UTC)
Message
you don't have the newest code on this page.

Looking at the "506" at the end of the number, it matched "six" before "sixteen" and the remaining "teen million..." in the string didn't fit the LPEG pattern so it stopped parsing.

Your "local ndigit =" lines are out of date.
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


143,152 views.

This is page 3, subject is 4 pages long:  [Previous page]  1  2  3 4  [Next page]

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]