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


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Lua
. . -> [Subject]  Remove Trailing Zeros

Remove Trailing Zeros

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


Posted by Xvordan   (29 posts)  [Biography] 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
[Go to top] top

Posted by Nick Gammon   Australia  (22,982 posts)  [Biography] 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
[Go to top] top

Posted by Xvordan   (29 posts)  [Biography] 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?
[Go to top] top

Posted by Fiendish   USA  (2,514 posts)  [Biography] 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
[Go to top] top

Posted by Nick Gammon   Australia  (22,982 posts)  [Biography] 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
[Go to top] top

Posted by Xvordan   (29 posts)  [Biography] 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
[Go to top] top

Posted by Fiendish   USA  (2,514 posts)  [Biography] 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
[Go to top] top

Posted by Nick Gammon   Australia  (22,982 posts)  [Biography] 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
[Go to top] 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] 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]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at HostDash]