Weird Number Value Problems

  • What are you attempting to achieve?
    I’m currently attempting to do a cooldown system where each skill has the amount of time until the end of the cooldown displayed on a GUI.

  • What is the issue?
    The number value appears to always turn into some weird huge decimal when subtracting 0.1, or just go to a completely random decimal rather than what the number value would supposed to be.
    Watch 2019-05-26 13-32-13 | Streamable

  • What solutions have you tried so far?
    I’ve tried setting the number values to 0 if they hit one of the random decimals, but this solution is inconsistent and messy. I’ve tried math.floor and math.ceil but they both just go to whole numbers.

5 Likes

Ah yes, you have encountered the dreaded Floating Point Error™ problem. There’s a whole lot of technical mumbo jumbo that I don’t understand that can be summarized as “Because of the way information is stored, NumberValues can’t hold most exact decimals, so it has to store an extremely close version of it instead.” Unless you’re comparing numbers in a script, it shouldn’t cause any issues–the difference is so minimal you’ll never notice. If you do need it to be perfectly accurate for the sake of comparing numbers in a script, the best solution I can provide is, in the script, processing the number a bit like so:

function deError(number)
    number=number*10 --we want to preserve the first decimal place
    if number-math.floor(number)>=0.5 then --round the number
        number=math.ceil(number)
    else
        number=math.floor(number)
    end
    return number/10 --return the processed number
end
13 Likes

Use an IntValue and handle your cooldowns in timestamps instead. When your action goes off check if the current os.time() is larger than the value of the IntValue and just set the value to os.time() + cooldown_time if so and continue with the action.

If you want your cooldown_time to have decimal places, just multiply your os.time() values by 10^n, where n is how many decimal places of accuracy you want; I suggest just 1 works.

1 Like

Use client-side prediction. Have the server set a clock ahead of time (using the method above - set a time to current time + usage interval) and have the client animate the countdown instead. Don’t actually change the value of a ValueObject over a period of time.

2 Likes

I’ll attempt each of these solutions, thank you.

A more concise version of Chipio’s function:

function deError(number)
	return math.floor(number*10 + 0.5)/10
end
function deError(number)
    return math.round(number*10)/10
end

Nothing more to add, these are all good solutions!

8 Likes