WoW - rounding to two decimal places in Lua
Asked Answered
M

3

10

I'm trying to display my total experience points as a percentage rounded to two decimals. I have come up with a solution, but its quite clunky. There has to be a better way.

Here is what I have:

local xpPercentage = (((UnitXP("player") / UnitXPMax("player"))*100))
-- 63.4587392473
local xpMantissa = xpPercentage - floor(xpPercentage)
-- .4587392473
local xpTwoDec = (floor(xpMantissa * 100)/100) + floor(xpPercentage)
-- 63.45

Again, this does what I want, but is there a prettier way to do it?

Mulberry answered 16/9, 2019 at 3:29 Comment(0)
C
14
local formatted = string.format(
   "%.2f %%",
   UnitXP('player') / UnitXPMax('player') * 100
)

That's the standard Lua way to do it, which should work for you as well. Unless WoW has removed that function, which would be silly.

Note that type(formatted) is String, not a number.


string.format, as described in the manual, takes a format string as its first argument, followed by a series of values you want to splice into the format string.

The format string will mostly be treated literally, except special tokens that start with %. The number of additional arguments should be equal to the number of these tokens in the format string.

In the example above, %f means "insert a float here"; for example, string.format("hello %f world", 5.1") would return "hello 5.1 world". Adding stuff after the % and before the f you can tell it how exactly to format it.

Here's an example using all the options: string.format("%x6.2f", 2.264)

From left to right:

  • % marks the start
  • x tells it to pad right with xs
  • 6 tells it the whole thing should be 5 characters long
  • .2 tells it to round (or pad with 0s) to 2 decimal places

So, the result would be xx2.26

Finally, since % holds special meaning in the format string, if you want a literal % you have to write %% instead.

"%.2f %%" thus means:

A float, rounded or padded to 2 decimals, followed by a space and a percent sign. The second argument to format must then be a number, or the function will error.

Carleencarlen answered 16/9, 2019 at 6:33 Comment(3)
All good answers. Thanks everyone. I'm new to Lua, so I'm still working the learning curve on getting on this stuff straight in my head. As a bonus, can you explain the "%.2f %%" syntax to me please?Mulberry
@Mulberry Sure thing ;)Carleencarlen
Fantastic. That is extremely helpful. Thank you very much!Mulberry
R
2

Here is a flexible function to round to different number of places. I tested it with negative numbers, big numbers, small numbers, and all manner of edge cases, and it is useful and reliable:

function Round(num, dp)
    --[[
    round a number to so-many decimal of places, which can be negative, 
    e.g. -1 places rounds to 10's,  
    
    examples
        173.2562 rounded to 0 dps is 173.0
        173.2562 rounded to 2 dps is 173.26
        173.2562 rounded to -1 dps is 170.0
    ]]--
    local mult = 10^(dp or 0)
    return math.floor(num * mult + 0.5)/mult
end
Rough answered 10/6, 2021 at 8:46 Comment(0)
B
0

There's already a good answer, but I'm unsure why you extract the mantissa at all, simply perform what you do with the mantissa on the whole number: multiply by 100, round (or floor) normally, then divide by 100.

If it helps, you can also view and write this as: divide by 0.01 (the precision you want to have) then round, then multiply by 0.01 again.

Lua doesn't have round, but to employ floor as a round function, simply use floor( x + 0.5 )
Although with percentages of levels, you might prefer a floor anyway, since displaying 0.995 as 100% would be misleading.

Beck answered 17/9, 2019 at 5:49 Comment(2)
"divide by 0.01" multiplying by 100 is "a lot" faster, at least on paper (IRL both of them are so fast you won't notice the difference), and it's also easier to read, so I don't see any reason why you'd divide by a fractionCarleencarlen
Well, it doesn't matter much to the computer, I wanted to hint that you could also use this method for other fractions, e.g. to multiples of 0.05 (Swiss currency has eliminated coins smaller than 5 Rappen = 0.05 Franken) or even crazy fractions that aren't fractions of 1, so that they would round integers to a non-integers.Beck

© 2022 - 2024 — McMap. All rights reserved.