Unreliable Number — A Non-Reliable Number... But wait!

Unreliable Number

A Non-Reliable Number… But wait!

GitHub | Documentation | Module

From the same creators of Unreliable Remote Events, Roblox presents — :tada:Unreliable Number — For when how a number looks is more important than what it actually is.

Well, just kidding… Kinda…

:question: Why “Unreliable”?

Because it intentionally sacrifices numeric precision in favor of formatting consistency and performance.

In simulation games, if a player has "1000T", we don’t care if they have exactly 1,000,000,000,000,000 or a little more — we care that the number still reads as "1000T". It’s perception over perfection.

Think of it like this:

  • Someone has 100.000.000 gold, and lets say that we have a precision of 8 digits (is adjustable the precision you want)
  • That player, getting more 9 gold or losing, its meaningless to that player, he can’t feel it, so why bother about it?
  • That’s what Unreliable is about, in this example, the last digit will always be 0, because is not an amount that matters to the player.

It’s not meant for accurate financial or scientific math.


:brain: Why Use This?

  • Perfect for simulation games with infinite scaling economies
  • Bypasses roblox max number limit (scales infinitely)
  • Has more performance with huge numbers than other modules
  • Handles numbers like "100000000M" with zero effort
  • Lightweight and Roblox-compatible
  • Takes formatting seriously (something most number wrappers don’t!)
Feature / Module BigNum InfiniteMath Gigantix Unreliable Number
Primary Focus Arbitrary-precision integers Numbers beyond 1e308 Efficient large-number math in Roblox Number Scaling “Infinitely” while keeping a good performance
Decimals :x: No :white_check_mark: Yes :x: No :white_check_mark: Yes
Supports Suffixes :x: No :white_check_mark: Yes :white_check_mark: Yes :white_check_mark: Yes
Negatives Support :white_check_mark: Yes :white_check_mark: Yes :x: No :white_check_mark: Yes
Ideal Use Case Complex math and precision Handling huge numbers Performance-focused number crunching Simulation/idle games, UI display
Math Precision :white_check_mark: High precision :white_check_mark: High (float-based) :warning: Limited :warning: Low — by design
Key Strength Math fidelity Extremely large float math Fast Roblox-side simulation math Format fidelity, marginal utility UX

:wrench: Installation

You can grab the module from here:
:link: Roblox Asset
:package: GitHub Source & Docs

local UnreliableNumber = require(path_to.UnreliableNumber)

:package: Unreliable Number Module API

🛠️ Setup

:hammer_and_wrench: Setup

Install and open the module, use ctrl+f to search for “config” and adjust the settings as you wish, this is the default values:

local config = {
	significantDigits = 20,       -- Maximum significant digits for the integer part
	significantDecimals = 4,      -- Maximum significant digits for the decimal part
	roundingMode = "nearest",     -- Rounding mode: "ceil", "floor", or "nearest"
	autoNormalize = true,		  -- Auto normalize the number (recommended)
	debug = false,                -- Debug mode for testing, outputs extra information
}

Place the module in ReplicatedStorage and import it on your script.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UnreliableNumber = require(ReplicatedStorage.UnreliableNumber)

🧱 Constructors

:brick: Constructors

UnreliableNumber.new(sign, integer, trailingZeros, decimal)

Create an instance directly.

local num = UnreliableNumber.new(1, "123", 0, "45") -- 123.45

UnreliableNumber.fromNumber(number)

Approximate from Lua number.

local approx = UnreliableNumber.fromNumber(1000.001)

UnreliableNumber.fromString(string)

Preserves original formatting.

local num = UnreliableNumber.fromString("00123.4500")
-- OR
local num2 = UnreliableNumber.newFromString("123.5_2") -- this is equals to 12300.5

UnreliableNumber.fromSuffix(string)

Supports suffixes like K/M/B/T…

local num = UnreliableNumber.fromSuffix("1.5K")

➕ Arithmetic

:heavy_plus_sign: Arithmetic

All arithmetic returns new UnreliableNumber instances. Also supports +/-*.

local a = UnreliableNumber.fromString("1000")
local b = UnreliableNumber.fromString("250")

local sum = a:add(b)
print(sum:toString()) -- ≈ "1250"

🧮 Methods Overview

:abacus: Methods Overview

:add(other), :subtract(other), :multiply(other), :divide(other)

Performs approximate arithmetic.

:clone()

Returns a deep copy.

:removeDecimals()

Strips the decimal portion.

:shiftLeft(n) / :shiftRight(n)

Adjusts decimal position visually.

:normalize()


🔍 Comparison

:mag: Comparison

Lexical/formatted comparison only. Also support => for example:

if num1:isGreater(num2) then
    print("Looks greater!")
end

Supported:

  • :isEqual()
  • :isGreater(), :isLesser()
  • :isGreaterOrEquals(), :isLesserOrEquals()
  • :compare() (returns -1, 0, 1)

🔁 Conversion

:repeat: Conversion

For number conversion:

local coins = UnreliableNumber.fromString("0001234.000")
coins:normalize({ trimLeadingZeros = true })
textLabel.Text = coins:toSuffix() -- "1.23K"
  • :toString() → Original or mutated full string
  • :toFullNumber() → Integer + Decimal as string
  • :toFullSuffix() / :toSuffix() → Suffix notation
  • :toNumber() → Lua number (approximate)
  • :serialize(raw) → String or number output

GitHub | Documentation | Module

5 Likes

I’m a little bit lost here. What’s the advantage over using regular numbers (+ suffix formatting module and rounding the number visually for the player) and then switching to a module like InfiniteMath (which also supports suffixes) once you hit Roblox’s number limit? Sacrificing precision seems like an unnecessary sacrifice that would also constrain development directions (e.g., simulator currency increase mechanisms must be above a certain point to affect the player’s amount)

1 Like

Nice question, I felt difficulty on putting my thoughts on the post, but I will try to answer your question:

Why not use InfiniteMath + Suffix Module?

Infinite Math has a major drawback compared to my module, it has a max number limit that if I am not wrong is like 10^^308 or something similar to that, what is not really a thing I want when my game can scale infinitely or almost infinitely, since someone would reach the limit.

Besides that, I don’t really know how smooth is the integration with a suffix module, but I am pretty sure that is fine, so with infinite math the main issue is only the max number limit.

Sacrificing precision

In my POV seems like more of a psychological thing, this module allows you to set a custom number of relevant digits, I sacrifice precision for scalability(theorically infinite), but well, lets go to what is important, and to that let me ask you a question first:

  • Do you think a player with 100000000Q$ would miss 10$?

Of course not, and that would come with the issue of a player with that amount buy infinitely of that resource, which in most games is a useless resource to someone with that amount of money, so it doesn’t really “matter”, since he would have to manually buy a lot of it, just as someone with 100000000Q$ would need to buy 1000000000Q manually of that resource.

I don’t know if I am getting my point to you. But basically, is more of a psychological thing, realistically, in most games, even if the player bought that amount of that resource, (besides the time to buy it), the value of the actual resource wouldn’t really be worth it. Of course it depends on the game, but for most games I played that was the case.

Data loss is data loss, and as such I rather avoid it. Losing user data is probably the worst that a developer can do, consciously at that

3 Likes

I understand what you are saying. Still, I stand for what I said since its not like the user will lose anything meaningful, but thank you for your feedback!

1 Like

what about EternityNum & EternityNum2?

1 Like

Never looked into them, might take a look at them later

Okey, I took a quick look at them, and seems like they also have a limit, just like InfiniteMath. It would fit most use cases, but again, if you want to scale infinitely that wouldn’t be the best module, since after some value it would cap and wouldnt increase/decrease more

I don’t really understand how this module could “scale infinitely”? The cap in InfiniteMath is quite large but never “infinite”. Modules like InfiniteMath also do not have extreme precision as storing all that would be extremely difficult. How does your module store data and why would choosing this module over say InfiniteMath which stores datas, allows for nearly every arithmetic function to be usable on InfiniteMath.new() numbers, and has a notation list which is quite high and changes to scientific notation afterwards be beneficial? From what I’m reading, your module doesn’t actually store numbers (correct me if I’m wrong [which I probably am!]).

1 Like

Ok there is a lot to say here so lets go step by step, first scale infinitely is just theorically given infinite memory, but can scale way more due to the “quirk” of significant digits, since the limit of infinite math is 309 digits, my module can go way above that, not sure with how many significant digits, but probably way less than infinite math. So here, if you want large number with precision Infinite Math is a lot better, if precision isnt a must, mine probably would be a better aproach depending on the type of game

My module stores the data as a string in the end since I am parsing the string to do the math in under the hood, but well, how it would look a number with 4 significant digits and with 1000 digits (zeros) would be like: 1234_1000, which in the end represents 1004 digits (1234 and 1000 zeros after those), which my module can handle with ease because of the way its handled. To be honest I didnt test how many signigicant digits my module can handle while keeping a good performance, since with my use cases I usually dont want more than 32 significant digits, but I might do some stress tests later if you want to know.

I also happen to have a similar list notation to convert the numbers to notation, which I need to expand further cuz my module is… “infinite”.

And what do you mean by dont store the numbers, when you create it, it creates the number as an object, but not sure if that is what you mean?

In the end: If you dont want to “lose irrelevant data” infinite math is the way, if you want something with no precision at all after the signigicant digits but can scale theorically infinite, the way is my module, in the end, in programming you cant have everything, you have to choose the best for your use case.

1 Like

Btw, to smooth a little the issue of losing data, I will soon add some type of caching system so when the value hits a relevant number, it does the operation correctly on the number, making the module a little bit more precise.

This is imo a really good idea, I think people fail to understand that 10$ means nothing when you have billions, and for it to accumulate to something meaningful, you would need millions of 10$ increases, which realistically doesn’t even happen in games

You don’t seem to talk about performance though, which imo would be the best benefit I can think of for using this method. Infinite precision can still be achieved without hitting a limit (if you let the number use more and more memory), just like your module, but using more and more memory probably makes math operations slower and slower

It is also a bit odd for the precision setting to use digits rather than bits or bytes, that probably depends on how you implemented the system internally? Although for the best performance, binary is probably the way to go

1 Like

You are right, you got exactly where I was trying to get, I ended up talking about performance here in the comments though… as always its hard to put my thoughts on a text lol!

About the binary implementation I never looked into it, I might look into it and revamp the whole module to have best performance, do you happen to have any resource where I should start looking into it?

Thanks for your comment! s2

1 Like

I don’t really know, you should look into the binary encoding for integers (floats are complicated…), and perhaps look into the buffer or bit32 library. The basic method of working with binary is number //= 2 to move to the next bit, and bit = number % 2 to extract the value of the current bit (0 or 1). By chaining these, you can move from the least significant bit to the most significant. You can also change the 2 to 256 (aka 2^8) to move to the next byte, or read the current byte (0 to 255). However, luau being a high level language, binary is not as effective