4
\$\begingroup\$

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
\$\endgroup\$
0

2 Answers 2

2
\$\begingroup\$

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

Working sample (and output):

-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
\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.