I’m certainly not the fastest with a keyboard, but I didn’t want to abandon this reply, so
The table of abbreviations
local abbreviations = {
[3] = "K";
[6] = "M";
[9] = "B";
[12] = "T"
}
This table is fine, but the following sections of this reply assume the table looks like this:
local abbreviations = {"K", "M", "B", "T"}
Which abbreviation do we want?
local abbreviation = abbreviations[floor(log10(n))/3]
To understand what’s wrong with this line, we should take a closer look at floor(log10(n))/3
.
very long table
n |
floor(log10(n)) |
floor(log10(n))/3 |
1 |
0 |
0.000 |
10 |
1 |
0.333 |
100 |
2 |
0.667 |
1000 |
3 |
1.000 |
10000 |
4 |
1.333 |
100000 |
5 |
1.667 |
1000000 |
6 |
2.000 |
10000000 |
7 |
2.333 |
100000000 |
8 |
2.667 |
1000000000 |
9 |
3.000 |
10000000000 |
10 |
3.333 |
100000000000 |
11 |
3.667 |
1000000000000 |
12 |
4.000 |
10000000000000 |
13 |
4.333 |
100000000000000 |
14 |
4.667 |
1000000000000000 |
15 |
5.000 |
With our new table of abbreviations, we get reasonable results for 1, 1000, 1000000, 1000000000, 1000000000000, and 1000000000000000.
But what about any other number of digits? One possible solution:
another very long table
n |
floor(log10(n)/3) |
1 |
0 |
10 |
0 |
100 |
0 |
1000 |
1 |
10000 |
1 |
100000 |
1 |
1000000 |
2 |
10000000 |
2 |
100000000 |
2 |
1000000000 |
3 |
10000000000 |
3 |
100000000000 |
3 |
1000000000000 |
4 |
10000000000000 |
4 |
100000000000000 |
4 |
1000000000000000 |
5 |
With one minor change, the line becomes
local abbreviation = abbreviations[floor(log10(n)/3)]
...what?
local res, concat = pcall(function()
return tostring(n):format("%.2f" .. abbreviation .. "+")
end)
if res then
else
return floor(n)
end
return concat
This can be avoided entirely with the solution posted by @Ninja_Deer. Feel free to ignore all of this and just use that solution instead.
But can we do better?
Unfortunately, the previously mentioned solution falls apart once you go beyond the defined abbreviations, so here’s my solution.
local abbreviations = {"K", "M", "B", "T"}
function format(n)
local b = math.min(math.floor(math.log10(n) / 3), #abbreviations)
local abbr = abbreviations[b]
if abbr then
return string.format("%.2f%s", n / (1000^b), abbr)
else
return string.format("%g", n) -- for consistency
end
end
oh no, another table!
n |
format(n) |
1 |
1 |
10 |
10 |
100 |
100 |
1000 |
1.00K |
10000 |
10.00K |
100000 |
100.00K |
1000000 |
1.00M |
10000000 |
10.00M |
100000000 |
100.00M |
1000000000 |
1.00B |
10000000000 |
10.00B |
100000000000 |
100.00B |
1000000000000 |
1.00T |
10000000000000 |
10.00T |
100000000000000 |
100.00T |
1000000000000000 |
1000.00T |
10000000000000000 |
10000.00T |