Suffixing numeric values

This is a part of my Factorio mod Visual Signals.

This code takes a numeric value as input and returns a string for the value, for example:

-12 --> -12
1 --> 1
50 --> 50
999 --> 999
1500 --> 1.5k
24999 --> 24.9k
123456 --> 123k
1234567 --> 1.2M
12345678 --> 12M
123456789 --> 123M
1234567890 --> 1.2G
and so on...


The idea is to replicate the same way Factorio show signals in the circuit network.

The code works by determining a prefix, which simply is a potential minus sign. It then determines the middle part (the numbers and potential comma separator to use) and the suffix (the letter at the end).

The code seems to work perfectly fine and now I simply wonder: Can I improve this code somehow?

local suffixChars = { "", "k", "M", "G", "T", "P", "E" }

function CountString(count)
local absValue = math.abs(count)
local prefix = ""
if count < 0 then
prefix = "-"
end
local suffix = 1
while absValue >= 1000 do
absValue = absValue / 1000
suffix = suffix + 1
end

local str = tostring(absValue)
if absValue < 10 then
return prefix .. string.sub(str, 1, 3) .. suffixChars[suffix]
end
if absValue < 100 then
return prefix .. string.sub(str, 1, 2) .. suffixChars[suffix]
end
return prefix .. string.sub(str, 1, 3) .. suffixChars[suffix]
end


First off, your naming convention. You have a function name CountString, which to me states that you are either counting a string (?) or something along those lines. A better name would be FriendlyNumber or HumaneNumber.

count in a similar manner, means tracking an iterator. It could become input, rawValue etc.

Now, to the actual function. You can make use of a log function to compute your suffix (base 10), and the same for referring to your index in suffix list, as well as getting the absValue.

Instead of concatenating different parts of string, use a string.format, which would also remove your call to tostring.

Lua has a ternary operator, which can be done using and..or statements. Based on your version of lua engine (4.x, 5.{1, 2, 3}), you might have different implementation of the log function. A sample code would be:

-- For Lua 5.1
local suffixChars = { "", "k", "M", "G", "T", "P", "E" }
local l, f, a = math.log10, math.floor, math.abs  -- Lua 5.2+ have math.log(x, base)

function FriendlyNumber(rawValue)
local absValue = a(rawValue)
local prefix = rawValue < 0 and "-" or ""
local log = f(l(absValue) / 3)
-- I was calculating log first, but I needed floor(1/3rd) of it,
-- and later had to multiply by 3 again, so computing the 1/3rd here only
local suffix = suffixChars[1 + log]
absValue = absValue / (10 ^ (log * 3))
local str = ("%%.%df"):format((absValue < 1000 and absValue > 10) and 0 or 1):format(absValue)
return ("%s%s%s"):format(prefix, str, suffix)
end


-12 -12
1.0 1
50  50
999 999
1.5k    1500
25k 24999
123k    123456
1.2M    1234567
12M 12345678
123M    123456789
1.2G    1234567890


Use built-in tools

The idea is to replicate the same way Factorio show signals in the circuit network.

Using the built-in sprite-button element and the number property it allows you to show signals just like Factorio shows them in a circuit network.