How can I fix this number abbreviations script?

If i were to put 1000 into the format function it’d return 1000 and not 1K or if I put 1000000 in it, it wouldn’t return 1M and so on.

I would like to salvage the code I’ve already written if possible!

local log10 = math.log10
local floor = math.floor

local abbreviations = {
	[3] = "K";
	[6] = "M";
	[9] = "B";
	[12] = "T"
}

function format(n)
	local abbreviation = abbreviations[floor(log10(n))/3]

	local res, concat = pcall(function()
		return tostring(n):format("%.2f" .. abbreviation .. "+")
	end)
	if res then
	else
		return floor(n)
	end
	return concat
end

game:GetService("RunService").RenderStepped:Connect(function(dt)
	wait(dt^2)
	print(format(game.Players.LocalPlayer.leaderstats.Trust.Value))
end)
2 Likes

Here you go! You were close:

function format(n)
    local zeros = floor(log10(n)/3)*3
	local abbreviation = abbreviations[zeros]
	if abbreviation then
	    return floor(n/(10^zeros)) .. abbreviation
	end
	return floor(n)
end
1 Like

I’ll try that out right now, thanks!

1 Like

Just wondering if I could make it so instead of 1250 = 1K it couldbe equal to 1.25K?

1 Like

By 1250 = 1.25K do you mean to the 3 significant digits or by 2 fractional digits?
For 2 fractional digits you change so that

floor(n / 10 ^ zeroes) .. abbreviation

becomes

string.format("%.2f", n / 10 ^ zeroes) .. abbreviation

I’ll try that for the 2 fractional digits rn, thanks!

1 Like

Thanks, @Blockzez, that worked nicely!

1 Like

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
2 Likes

Just as an FYI, if you want to take a number like 1200 and change it to 1.2K and not 1.20K (and 1000 to 1K and not 1.00K), you can do so like this:

function format(n)
    local zeros = floor(log10(n)/3)*3
	local abbreviation = abbreviations[zeros]
	if abbreviation then
	    local s = string.format("%.2f",n/(10^zeros)):gsub("%.00","")
	    local x = string.find(s,"%..0")
	    if x then
	       s = string.sub(s,1,x+1)
	    end
	    return s..abbreviation
	end
	return floor(n)
end
1 Like

Haha, sorry about that. Your response was excellent and you simplified his table as well!

1 Like

Another suggestion:

	if abbreviation then
	    local s = string.format("%.3g",n/(10^zeros))
	    return s..abbreviation
	end
n string.format("%.3g", n)
1.2345 1.23
12.345 12.3
123.45 123
1234.5 1.23e+03 (oh)
12345 1.234e+04 (ouch)

…well, it was worth a shot

1 Like

Thanks to everybody who replied, all the replies have been a great help! :smiley:

2 Likes

I was able to mix all your suggestions together to make this flawless number abbreviations script

local log10 = math.log10
local floor = math.floor
local min = math.min

local number = 0

game.Players.LocalPlayer.Chatted:Connect(function(msg)
	number = string.match(msg, "%d+")
end)

local abbreviations = {
	"K";
	"M";
	"B";
	"T";
	"Qd";
	"Qu";
	"Sx"
}

function format(n)
	local b = min(floor(log10(n) / 3), #abbreviations)
	local abbr = abbreviations[b]
	if abbr then
	else
		return floor(n)
	end
	local s = ("%.2f%s"):format(n / (1000^b), abbr):gsub("%.00","")
	local x = s:find("%..0")
	if x then
		s = s:sub(1,x+1)
	end
	return s .. "+"
end

game:GetService("RunService").RenderStepped:Connect(function(dt)
	wait(dt^2)
	print(format(number))
end)

It works perfectly, thanks to everybody who helped! :smiley:

3 Likes
	if not abbr then
		return floor(n)
	end