Numbers not rounding right

Hey devs,
I havent been able to figure out this problem even though its something so easy, The numbers always are being rounded to supper long decimals and I cant figure it out! Any ideas on how to fix this?

local function animateCount(label, start, finish)
	local diff = finish - start
	local duration = math.clamp(math.abs(diff) / 50, 0.2, 1)
	local steps = 30
	for i = 1, steps do
		local alpha = i / steps
		local current = start + diff * alpha
		if math.abs(finish) >= 1000 then
			label.Text = Formatter.checkzeros(current, 1)
		else
			label.Text = string.format("%.1f", current)
		end
		task.wait(duration / steps)
	end
	if math.abs(finish) >= 1000 then
		label.Text = Formatter.checkzeros(finish, 1)
	else
		label.Text = tostring(finish)
	end
end

1 Like

You can round the number before you convert it to string. Multiply by your desired precision (e.g. 100 for two digits), math.round() and then divide by 100. This will output 45.42.

print(math.round(45.424623452345 * 100) / 100) -- 45.42

There’s a way to do it with string.format() as well.

print(string.format("%.2f",45.424623452345)) -- 45.42
1 Like

So how would I incorporate that into my script so it works?

I think you want it each of the times you set. the label.Text property. There’s already a round to 1 digit of precision on the line in the steps loop. You can add that to the line outside of the loop as well.

I’m not sure what Formatter does. If it’s a library then it might have a function that handles precision. If the output of Formatter.checkzeros() is good then you might just need to use that on each of the labels. The conditional wouldnt’ be needed if this works.

Floating-point math isn’t exact, but you can force clean rounding by quantizing current before displaying..

local function animateCount(label, start, finish)
	local diff = finish - start
	local duration = math.clamp(math.abs(diff) / 50, 0.2, 1)
	local steps = 30
	for i = 1, steps do
		local alpha = i / steps
		local current = math.floor((start + diff * alpha) * 10 + 0.5) / 10
		if math.abs(finish) >= 1000 then
			label.Text = Formatter.checkzeros(current, 1)
		else
			label.Text = string.format("%.1f", current)
		end
		task.wait(duration / steps)
	end
	if math.abs(finish) >= 1000 then
		label.Text = Formatter.checkzeros(finish, 1)
	else
		label.Text = tostring(finish)
	end
end

This rounds to one decimal consistently before formatting.

local current = math.floor((start + diff * alpha) * 10 + 0.5) / 10
Client Test Script
local label = Instance.new("TextLabel")
label.Size = UDim2.new(0,200,0,50)
label.Position = UDim2.new(0.5,-100,0.5,-25)
label.TextScaled = true
label.Parent = game.Players.LocalPlayer:WaitForChild("PlayerGui")

local Formatter = {}
function Formatter.checkzeros(num, dec)
	return string.format("%."..dec.."f", num)
end

local function animateCount(label, start, finish)
	local diff = finish - start
	local duration = math.clamp(math.abs(diff) / 50, 0.2, 1)
	local steps = 30
	for i = 1, steps do
		local alpha = i / steps
		local current = math.floor((start + diff * alpha) * 10 + 0.5) / 10
		print("Current:", current)
		if math.abs(finish) >= 1000 then
			label.Text = Formatter.checkzeros(current, 1)
		else
			label.Text = string.format("%.1f", current)
		end
		task.wait(duration / steps)
	end
	if math.abs(finish) >= 1000 then
		label.Text = Formatter.checkzeros(finish, 1)
	else
		label.Text = tostring(finish)
	end
end

print("Starting animation")
animateCount(label, 0, 1234)
print("Done")
1 Like

This is the full script Im not sure why its still happening

local TweenService = game:GetService("TweenService")
local Formatter = require(game.ReplicatedStorage.Server.Modules.Helpers.Formatter)

local module = {}

module.Profiles = {}

local function animateCount(label, start, finish)
	local diff = finish - start
	local duration = math.clamp(math.abs(diff) / 50, 0.2, 1)
	local steps = 30
	for i = 1, steps do
		local alpha = i / steps
		local current = math.floor((start + diff * alpha) * 10 + 0.5) / 10
		if math.abs(finish) >= 1000 then
			label.Text = Formatter.checkzeros(current, 1)
		else
			label.Text = string.format("%.1f", current)
		end
		task.wait(duration / steps)
	end
	if math.abs(finish) >= 1000 then
		label.Text = Formatter.checkzeros(finish, 1)
	else
		label.Text = tostring(finish)
	end
end

local function animateAddText(CoinsAdd, startPos)
	CoinsAdd.TextTransparency = 1
	CoinsAdd.UIStroke.Transparency = 1
	CoinsAdd.Size = UDim2.new(0, 0, 0, 0)
	CoinsAdd.Position = startPos

	local popTweenInfo = TweenInfo.new(0.25, Enum.EasingStyle.Back, Enum.EasingDirection.Out)
	local floatTweenInfo = TweenInfo.new(0.75, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
	local fadeTweenInfo = TweenInfo.new(0.4, Enum.EasingStyle.Sine, Enum.EasingDirection.Out, 0, false, 0.5)

	TweenService:Create(CoinsAdd, TweenInfo.new(0.1), {TextTransparency = 0, Size = UDim2.new(0, 80, 0, 40)}):Play()
	TweenService:Create(CoinsAdd.UIStroke, TweenInfo.new(0.1), {Transparency = 0}):Play()
	TweenService:Create(CoinsAdd, popTweenInfo, {Size = UDim2.new(0, 100, 0, 50)}):Play()

	task.wait(0.25)

	local floatGoal = startPos + UDim2.new(0, 0, -0.05, 0)
	TweenService:Create(CoinsAdd, floatTweenInfo, {Position = floatGoal}):Play()
	TweenService:Create(CoinsAdd, fadeTweenInfo, {TextTransparency = 1}):Play()
	TweenService:Create(CoinsAdd.UIStroke, fadeTweenInfo, {Transparency = 1}):Play()

	task.wait(1)
	CoinsAdd:Destroy()
end

function module.GiveRolls(player: Player, amount: number)
	local profile = module.Profiles[player]
	if not profile then return end
	local Coins = player.PlayerGui.ButtonsGUI.Currency.Rolls
	local old = profile.Data.Rolls
	profile.Data.Rolls += amount

	local CoinsAdd = Coins.Add:Clone()
	CoinsAdd.Parent = Coins
	CoinsAdd.Visible = true
	CoinsAdd.Text = "+" .. amount
	CoinsAdd.Rotation = math.random(-10, 10)
	CoinsAdd.Position = UDim2.new(0.66, math.random(-10, 10), 0.108, math.random(-5, 5))

	task.spawn(function()
		animateAddText(CoinsAdd, UDim2.new(0.66, 0, 0.108, 0))
	end)

	script.Sound:Play()
	animateCount(Coins.TextLabel, old, profile.Data.Rolls)
end

function module.RemoveRolls(player: Player, amount: number)
	local profile = module.Profiles[player]
	if not profile then return end
	local Coins = player.PlayerGui.ButtonsGUI.Currency.Rolls
	local old = profile.Data.Rolls
	profile.Data.Rolls -= amount

	local CoinsAdd = Coins.Add:Clone()
	CoinsAdd.Parent = Coins
	CoinsAdd.Visible = true
	CoinsAdd.Text = "-" .. amount
	CoinsAdd.Rotation = math.random(-10, 10)
	CoinsAdd.Position = UDim2.new(0.66, math.random(-10, 10), 0.108, math.random(-5, 5))

	task.spawn(function()
		animateAddText(CoinsAdd, UDim2.new(0.66, 0, 0.108, 0))
	end)

	script.Sound:Play()
	animateCount(Coins.TextLabel, old, profile.Data.Rolls)
end

function module.GiveRoPoints(player: Player, amount: number)
	local profile = module.Profiles[player]
	if not profile then return end
	local Coins = player.PlayerGui.ButtonsGUI.Currency.Coins
	local old = profile.Data.Credits
	profile.Data.Credits += amount
	player.leaderstats["💰 RoPoints"].Value = profile.Data.Credits

	local CoinsAdd = Coins.Add:Clone()
	CoinsAdd.Parent = Coins
	CoinsAdd.Visible = true
	CoinsAdd.Text = "+" .. amount
	CoinsAdd.Rotation = math.random(-10, 10)
	CoinsAdd.Position = UDim2.new(0.454, math.random(-10, 10), 0.563, math.random(-5, 5))

	task.spawn(function()
		animateAddText(CoinsAdd, UDim2.new(0.454, 0, 0.563, 0))
	end)

	script.Sound:Play()
	animateCount(Coins.TextLabel, old, profile.Data.Credits)
end

function module.RemoveRoPoints(player: Player, amount: number)
	local profile = module.Profiles[player]
	if not profile then return end
	local Coins = player.PlayerGui.ButtonsGUI.Currency.Coins
	local old = profile.Data.Credits
	profile.Data.Credits -= amount
	player.leaderstats["💰 RoPoints"].Value = profile.Data.Credits

	local CoinsAdd = Coins.Add:Clone()
	CoinsAdd.Parent = Coins
	CoinsAdd.Visible = true
	CoinsAdd.Text = "-" .. amount
	CoinsAdd.Rotation = math.random(-10, 10)
	CoinsAdd.Position = UDim2.new(0.454, math.random(-10, 10), 0.563, math.random(-5, 5))

	task.spawn(function()
		animateAddText(CoinsAdd, UDim2.new(0.454, 0, 0.563, 0))
	end)

	script.Sound:Play()
	animateCount(Coins.TextLabel, old, profile.Data.Credits)
end

function module.GiveRollsDones(player: Player, amount: number)
	local profile = module.Profiles[player]
	if not profile then return end
	profile.Data.RollsDone += amount
	player.leaderstats["🎲 Rolls"].Value = profile.Data.RollsDone
end

function module.GetRolls(player: Player)
	local profile = module.Profiles[player]
	if not profile then return end
	return profile.Data.Rolls
end

function module.GetRoPoints(player: Player)
	local profile = module.Profiles[player]
	if not profile then return end
	return profile.Data.Credits
end

function module.AdjustRolls(player: Player, amount: number)
	local profile = module.Profiles[player]
	if not profile then return end
	local Coins = player.PlayerGui.ButtonsGUI.Currency.Rolls
	profile.Data.Rolls = amount
	Coins.TextLabel.Text = profile.Data.Rolls
end

function module.AdjustRoPoints(player: Player, amount: number)
	local profile = module.Profiles[player]
	if not profile then return end
	local Coins = player.PlayerGui.ButtonsGUI.Currency.Coins
	profile.Data.Credits = amount
	player.leaderstats["💰 RoPoints"].Value = profile.Data.Credits
	Coins.TextLabel.Text = Formatter.checkzeros(profile.Data.Credits, 1)
end

function module.AdjustTimer(player: Player, amount: number)
	local profile = module.Profiles[player]
	if not profile then return end
	profile.Data.Timer = amount
end

function module.GetLoginTimes(player: Player)
	local profile = module.Profiles[player]
	if not profile then return end
	return profile.Data.LoginTimes
end

function module.GetTimer(player: Player)
	local profile = module.Profiles[player]
	if not profile then return end
	return profile.Data.Timer
end

return module
---
1 Like

If the issue happens specifically with numbers smaller than 1000 then it may be because of your last tostring(finish) case. It doesn’t round the result like the other ones do. This is assuming Formatter.checkzeros rounds results because we don’t have code for that.

The issue seems to originate in the required module:

function Formatter.checkzeros(num, dec)
	num = math.floor(num * 10^dec + 0.5) / 10^dec
	return string.format("%."..dec.."f", num)
end

This should get that rolling.

Basically I’m just rounding the numbers first, then formatting them, so the text always shows clean, exact decimals instead of floating-point noise.

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