Number Abbreviation Notation System

I made a script function that will abbreviate any number inserted into it with the proper notation selected for it (scientific as 1 or letters as 2, letters is default):

function Abbreviate(numberHere,Notation) -- Notation: 1 = Scientific, 2 = Letters, Default = 2 
	local DigitsInNumber = math.max(math.ceil(math.log10(numberHere+1)),1) 
	
	local FormattedNumber 
	local NotationToUse 
	if Notation == 1 then -- Scientific Notation 
		FormattedNumber = string.sub(tostring(numberHere/10^(DigitsInNumber-1)),1,3) 
		NotationToUse = FormattedNumber.."e"..DigitsInNumber-1 
	elseif (Notation and Notation == 2) or not Notation then -- Letters 
		local TableOfLetters = { 
			"", 
			"K", 
			"M", 
			"B", 
			"T", 
			"Qa", 
			"Qi", 
			"Sx", 
			"Sp", 
			"Oc", 
			"No", 
			"Dc", 
			"Ud", 
			"Dd" 
		} 
		local NumberOfDigitsToShow = 1.5*(DigitsInNumber%3)^2 - 3.5*(DigitsInNumber%3) + 5 -- (0,5), (1,3), (2,4) 
		FormattedNumber = string.sub(tostring(numberHere/10^(DigitsInNumber-1)),1,NumberOfDigitsToShow) 
		local FinalNumber = string.sub(FormattedNumber*(10^((DigitsInNumber-1)%3)),1,NumberOfDigitsToShow) 
		if DigitsInNumber == 3 then 
			FinalNumber = tostring(math.ceil(tonumber(FinalNumber))) -- For floating point errors 
		end 
		NotationToUse = FinalNumber..TableOfLetters[math.ceil(DigitsInNumber/3)] 
	end 
	return NotationToUse 
end 

print(Abbreviate(2530)) -- Example of usage for letter format 
print(Abbreviate(2530,1)) -- Example of usage for scientific notation 

I have already made quite a lot of improvements to it and made it more accurate as well. The way that I want to improve it is by making it possibly faster to run (all the math will probably make it run slower I assume?) Is there a way to remove any of the math but still get the same numbers needed? Scientific works well, specifically talking about getting less math for the letter notation if possible

local suffixes = {
	"",
	"K",
	"M",
	"B",
	"T",
	"Qa",
	"Qi",
	"Sx",
	"Sp",
	"Oc",
	"No",
	"Dc",
	"Ud",
	"Dd"
}

function abbreviate(number)
	local abbreviationFactor = math.floor(math.floor(math.log10(number)) / 3)
	local abbreviation = ""
	if abbreviationFactor > 0 then
		abbreviation = string.format("%.2f", number / 10 ^ (abbreviationFactor * 3)) .. suffixes[abbreviationFactor + 1]
	else
		abbreviation = tostring(number)
	end

	return abbreviation
end

print(abbreviate(5320))

By using string format we should be able to avoid some of those pesky math calculations. You can add the notations to the script above. Another optimization would to be remove the table from inside the function. Since you don’t want a table to be created everytime the function is called.

3 Likes

There are a few ways you could potentially optimize this function:

  1. Instead of using math.max(math.ceil(math.log10(numberHere+1)),1) to compute the number of digits in numberHere , you could use the # operator to compute the length of the string representation of numberHere . This would eliminate the need for the math.log10 and math.ceil calls:

Copy code

local DigitsInNumber = #tostring(numberHere)
  1. Instead of using a lookup table for the letter notation abbreviations, you could compute the abbreviation using simple math operations. For example, you could use the modulo operator ( % ) and integer division ( // ) to determine the abbreviation based on the number of digits in numberHere :
local abbreviations = { 
  "", 
  "K", 
  "M", 
  "B", 
  "T", 
  "Qa", 
  "Qi", 
  "Sx", 
  "Sp", 
  "Oc", 
  "No", 
  "Dc", 
  "Ud", 
  "Dd" 
}
local abbreviation = abbreviations[DigitsInNumber // 3 + 1]
  1. Instead of using the string.sub function to extract a substring from the string representation of numberHere , you could use the string.format function to format numberHere as a string with a specific number of decimal places. This would eliminate the need for the string.sub call and the additional floating point arithmetic:
local formattedNumber = string.format("%.1f", numberHere / 10^(DigitsInNumber-1))

Here is the complete code:
Here is the revised function using the suggestions I provided:

Copy code

function Abbreviate(numberHere, notation)
  -- notation: 1 = Scientific, 2 = Letters, Default = 2 
  local digitsInNumber = #tostring(numberHere)

  local formattedNumber
  local notationToUse
  if notation == 1 then -- Scientific Notation 
    formattedNumber = string.format("%.1f", numberHere / 10^(digitsInNumber-1))
    notationToUse = formattedNumber .. "e" .. digitsInNumber-1
  elseif (notation and notation == 2) or not notation then -- Letters 
    local abbreviations = { 
      "", 
      "K", 
      "M", 
      "B", 
      "T", 
      "Qa", 
      "Qi", 
      "Sx", 
      "Sp", 
      "Oc", 
      "No", 
      "Dc", 
      "Ud", 
      "Dd" 
    }
    local abbreviation = abbreviations[digitsInNumber // 3 + 1]
    formattedNumber = string.format("%.1f", numberHere / 10^(digitsInNumber-1))
    notationToUse = formattedNumber .. abbreviation
  end 
  return notationToUse 
end 

print(Abbreviate(2530)) -- Example of usage for letter format 
print(Abbreviate(2530, 1)) -- Example of usage for scientific notation 

This revised function should be faster and more efficient than the original version. Let me know if you have any further questions!

Thank you for the idea of putting the table outside of the function and the better use of string.format() (I originally planned to use it, but I was not very good at it and didn’t realize it could be used more efficiently than the math)

And thank you for shortening my digits in number and getting the abbreviation quicker, although, // does not exist, so I just changed it to the equivalent of math.floor(DigitsInNumber/3)

I’d set both of you guys as the solution, but I can’t, so I’ll just set the solution to the one that answered first, again thank you both!

no problem! good luck with your game! :heart:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.