Gammon Forum
Entire forum
MUSHclient
Lua
Remove Trailing Zeros
It is now over 60 days since the last post. This thread is closed.
  Refresh page
Posted by
| Xvordan
(29 posts) bio
|
Date
| Wed 07 Oct 2015 01:58 PM (UTC) |
Message
| I'm playing a mud which uses inhumanely huge numbers. In an effort to curtail the onslaught of numbers on my screen, I wrote a function that converts values like 8,000,000,000 into "8 billion".
I'm using a division method, and it works well when paired with string.format to narrow the result down to only one decimal place, like 8.3 billion. My problem is that string.format also likes to make a whole number a decimal, so 100 billion becomes 100.0 billion.
I tried fixing it with string.gsub(string, "%.0", ""), but it didn't seem to do anything to the results -- I'm still getting 100.0 million. Anyone know of a good solution? I really don't want to do math.floor or rounding it down or anything like that, since if there is a useful decimal like 8.6, I want to keep it.
Function follows:
function truncate (s_trunc)
s_trunc = string.gsub(s_trunc, ",", "")
n_trunc = tonumber(s_trunc)
if (string.len(s_trunc) >= 1) and (string.len(s_trunc) <= 3) then
return s_trunc
elseif (string.len(s_trunc) >= 4) and (string.len(s_trunc) <= 6) then
n_divide = 1000
n_class = "thousand"
elseif (string.len(s_trunc) >= 7) and (string.len(s_trunc) <= 9) then
n_divide = 1000000
n_class = "million"
elseif (string.len(s_trunc) >= 10) and (string.len(s_trunc) <= 12) then
n_divide = 1000000000
n_class = "billion"
elseif (string.len(s_trunc) >= 13) and (string.len(s_trunc) <= 15) then
n_divide = 1000000000000
n_class = "trillion"
elseif (string.len(s_trunc) >= 16) and (string.len(s_trunc) <= 18) then
n_divide = 1000000000000000
n_class = "quadrillion"
elseif (string.len(s_trunc) >= 19) and (string.len(s_trunc) <= 21) then
n_divide = 1000000000000000000
n_class = "quintillion"
elseif (string.len(s_trunc) >= 22) and (string.len(s_trunc) <= 24) then
n_divide = 1000000000000000000000
n_class = "sextillion"
elseif (string.len(s_trunc) >= 25) and (string.len(s_trunc) <= 27) then
n_divide = 1000000000000000000000000
n_class = "septillion"
elseif (string.len(s_trunc) >= 28) and (string.len(s_trunc) <= 30) then
n_divide = 1000000000000000000000000000
n_class = "octillion"
else
return "error"
end
return string.gsub(string.format("%.1f", n_trunc/n_divide), "%.0", "").." "..n_class
end
| top |
|
Posted by
| Nick Gammon
Australia (22,982 posts) bio
Forum Administrator |
Date
| Reply #1 on Wed 07 Oct 2015 07:57 PM (UTC) |
Message
| See http://www.gammon.com.au/forum/?id=10155
Anyway, modifying your idea somewhat this seems to work:
function truncate (str)
str = string.gsub(str, ",", "") -- get rid of commas
len = string.len (string.match (str, "%d+")) -- find size of integer portion
if (len >= 1) and (len <= 3) then
return str
elseif (len >= 4) and (len <= 6) then
divideBy = 1E3
numberSize = "thousand"
elseif (len >= 7) and (len <= 9) then
divideBy = 1E6
numberSize = "million"
elseif (len >= 10) and (len <= 12) then
divideBy = 1E9
numberSize = "billion"
elseif (len >= 13) and (len <= 15) then
divideBy = 1E12
numberSize = "trillion"
elseif (len >= 16) and (len <= 18) then
divideBy = 1E15
numberSize = "quadrillion"
elseif (len >= 19) and (len <= 21) then
divideBy = 1E18
numberSize = "quintillion"
elseif (len >= 22) and (len <= 24) then
divideBy = 1E21
numberSize = "sextillion"
elseif (len >= 25) and (len <= 27) then
divideBy = 1E24
numberSize = "septillion"
elseif (len >= 28) and (len <= 30) then
divideBy = 1E27
numberSize = "octillion"
else
return "number error: " .. str
end
-- divide down, convert to float, omit trailing ".0", show one decimal place
return string.gsub(string.format("%.1f", tonumber(str)/divideBy), "%.0", "") .. " " .. numberSize
end
print (truncate ("8,600,000,000.22"))
print (truncate ("1234.567"))
print (truncate ("123.456"))
print (truncate ("8,000,000,000."))
Output:
8.6 billion
1.2 thousand
123.456
8 billion
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | top |
|
Posted by
| Xvordan
(29 posts) bio
|
Date
| Reply #2 on Thu 08 Oct 2015 09:41 AM (UTC) |
Message
| Thanks Nick! I'm not sure why your version worked and mine didn't, since I think that at the final step, ours looked fairly similar, and I'm not actually sure what I did wrong to make gsub not strip out the trailing 0's.
A problem with string.format, though: it likes to round up, converting 999999.999 to 1 million, so I end up with things like 1000 thousand when I truncate that number, which I'm sure looks strange to more than just me. Is there any way to keep it from rounding, and just displaying the number as 999999.9? | top |
|
Posted by
| Fiendish
USA (2,514 posts) bio
Global Moderator |
Date
| Reply #3 on Thu 08 Oct 2015 03:05 PM (UTC) |
Message
| If you don't want it to round, try subtracting sign*0.05 from your number first. |
https://github.com/fiendish/aardwolfclientpackage | top |
|
Posted by
| Nick Gammon
Australia (22,982 posts) bio
Forum Administrator |
Date
| Reply #4 on Thu 08 Oct 2015 07:52 PM (UTC) Amended on Thu 08 Oct 2015 07:54 PM (UTC) by Nick Gammon
|
Message
| The "fix" was that I took the length of the integer portion (third line).
As for the rounding, Fiendish's suggestion seems to work:
return string.gsub(string.format("%.1f", tonumber(str)/divideBy - 0.05), "%.0", "") .. " " .. numberSize
Although that might fail for small numbers. You might want to conditionally do it, depending on how big "len" is.
Actually, for small numbers, the divide is bypassed, so that could be OK. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | top |
|
Posted by
| Xvordan
(29 posts) bio
|
Date
| Reply #5 on Sat 10 Oct 2015 08:39 AM (UTC) |
Message
| Thanks Fiendish and Nick. You guys have been amazingly helpful. Though, I discovered that working with numbers in this way isn't always the best, since Lua doesn't like such huge numbers anyway. I just ran across the pages talking about the BC library, so I'm gonna have a go at using bc to help me make this work even better. I, for example, can't do any operations on the values I extrapolate from the mud, since about 90% of the numbers this mud uses are over the 2^52 limit. For example, my experience is now 104,906,932,793,409,552,121,856, and I need to see what x times that is to get to my next point. lol. Don't be surprised to hear from me again with BC, though. I really am not great with math.
Kai | top |
|
Posted by
| Fiendish
USA (2,514 posts) bio
Global Moderator |
Date
| Reply #6 on Sat 10 Oct 2015 01:10 PM (UTC) Amended on Sat 10 Oct 2015 11:00 PM (UTC) by Fiendish
|
Message
| I would just not tonumber the whole thing. You only ever need to look at the first three to five digits.
Your numeric output is essentially following the format of: "first_one_to_three_digits." followed by math.floor(next_digit.next_digit + 0.5)
You can easily check if that following part is zero before appending it. |
https://github.com/fiendish/aardwolfclientpackage | top |
|
Posted by
| Nick Gammon
Australia (22,982 posts) bio
Forum Administrator |
Date
| Reply #7 on Sat 10 Oct 2015 08:54 PM (UTC) |
Message
| The BC library can certainly handle large numbers like that, once you remove the commas. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | 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.
21,394 views.
It is now over 60 days since the last post. This thread is closed.
  Refresh page
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.