Posted by
| Nick Gammon
Australia (23,122 posts) Bio
Forum Administrator |
Message
| Here are three handy functions I have been working on recently:
Round
Need to round a number? This function rounds any number to the closest integer. The "tricky" case is exactly half-way. That is, should 1.5 round to 1 or 2? How about -1.5?
This function rounds 1.5 "up" to 2, and -1.5 "down" to -2.
-- round "up" to absolute value, so we treat negative differently
-- that is, round (-1.5) will return -2
function round (x)
if x >= 0 then
return math.floor (x + 0.5)
end -- if positive
return math.ceil (x - 0.5)
end -- function round
Rather fascinatingly, there are lots of ways of calculating rounding. See this article, for example:
http://en.wikipedia.org/wiki/Rounding
The method implemented above is the Symmetric Arithmetic Rounding algorithm. It has the slight flaw that it always rounds upwards on exactly x.5, whereas you could argue that it is equally valid to round down.
Other, more complicated methods, like Bankers' Rounding, round sometimes up and sometimes down, in order to even out the slight bias that rounding up gives. However for applications like computer games, the difference is probably not significant.
Duration
This function is designed to display a time interval in "short form". That is, rounded to the nearest major time interval. Some examples of intervals:
- 3.6 days - displays "4 d"
- 3.5 days - displays "4 d"
- 3.4 days - displays "3 d"
- 3.6 hours - displays "4 h"
- 3.5 hours - displays "4 h"
- 3.4 hours - displays "3 h"
- 3.6 minutes - displays "4 m"
- 3.5 minutes - displays "4 m"
- 3.4 minutes - displays "3 m"
- 59 seconds - displays "59 s"
- 58 seconds - displays "58 s"
- 57 seconds - displays "57 s" ... and so on to "0 s"
The intention here is to keep track of something, like how long you estimate it will take to level up, or how long a spell will take to wear off, or the time till the next "tick".
If you estimate that you will level in 4+ hours, then you don't really care about the number of seconds. In other words, something like this is too much information: "4h 15m 32s". This is especially true if the number is an estimate.
function convert_time (secs)
-- handle negative numbers
local sign = ""
if secs < 0 then
secs = math.abs (secs)
sign = "-"
end -- if negative seconds
-- weeks
if secs >= (60 * 60 * 24 * 6.5) then
return sign .. round (secs / (60 * 60 * 24 * 7)) .. " w"
end -- 6.5 or more days
-- days
if secs >= (60 * 60 * 23.5) then
return sign .. round (secs / (60 * 60 * 24)) .. " d"
end -- 23.5 or more hours
-- hours
if secs >= (60 * 59.5) then
return sign .. round (secs / (60 * 60)) .. " h"
end -- 59.5 or more minutes
-- minutes
if secs >= 59.5 then
return sign .. round (secs / 60) .. " m"
end -- 59.5 or more seconds
-- seconds
return sign .. round (secs) .. " s"
end -- function convert_time
Note that this function requires the "round" function mentioned above.
The reason for the transition points not being exactly on the day/hour/minute etc. is because of rounding. If we switched to showing seconds (rather than minutes) at exactly the 60-second point, then 59.9 seconds would be rounded up to "60 s". However 60 seconds should be displayd as "1 m", not "60 s". Thus, we transition at the point at which rounding will stop happening.
Commas in numbers
This function adds commas to big numbers. For example 123456 xp becomes "123,456".
function commas (num)
assert (type (num) == "number" or
type (num) == "string")
local result = ""
-- split number into 3 parts, eg. -1234.545e22
-- sign = + or -
-- before = 1234
-- after = .545e22
local sign, before, after =
string.match (tostring (num), "^([%+%-]?)(%d*)(%.?.*)$")
-- pull out batches of 3 digits from the end, put a comma before them
while string.len (before) > 3 do
result = "," .. string.sub (before, -3, -1) .. result
before = string.sub (before, 1, -4) -- remove last 3 digits
end -- while
-- we want the original sign, any left-over digits, the comma part,
-- and the stuff after the decimal point, if any
return sign .. before .. result .. after
end -- function commas
|
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|