[31.1] FormatNumber - A module for formatting numbers

Features

I decided to keep track of the features for this module, here’s the features I might add:

:heavy_check_mark: - the feature is available in this module
:x: - the feature is not available in this moudle because I don’t believe it makes sense to include it
:soon: - the feature is not available in this module yet but I’m working on it
:woman_shrugging: - the feature is not available in this module yet, but we might include it at some point.

International (NumberFormat and PluralRules)

Feature Status Notes
Formatting to parts :heavy_check_mark: Is isn’t easy to implement but if there are use cases I might add it
Formatting range :heavy_check_mark: But it’s experemental
Number formatter class :x: I don’t think there’s a use case for this. The purpose of NumberFormat class for International is so that it doesn’t have to go to the CLDR tree every time just to format the number. Doesn’t apply here. I also want this to be easy to use for scripters, just call the function and you get the number formatted. If you really like this style, use International or Unicode ICU.
Scientific/Engineering notation :heavy_check_mark:
Unit formatting :x: Not adding plural rules and this requires plural rules.
Plural rules :x: Aside from decimal places, workaround is trivial for English n == 1 and "one" or "other"
Treat currency as ISO 4217 code instead of a symbol :x: Do you have a use case for this on Roblox? and I’m considering custom currency option for International :slight_smile:
Compact notation :heavy_check_mark: (short with no plurals), :x: We did add compactPattern. For pluralised compact pattern like 1 Million but 2 Millionen, it’s better left to International and no use case here.
Locale argument :x: This isn’t locale-based
“compact” as a notation option :woman_shrugging: Previous version of FormatNumber have it as separate function, but we’ll see
More numbering system :heavy_check_mark:
Sign display option :woman_shrugging:
Currency sign display option :woman_shrugging:

Unicode ICU

Feature Status Notes
More fraction-significant rounding :heavy_check_mark: Experemental
Rule based number formatting :x: I want this moudle to be simple as possible. RBNF is a complex thing to implement and was experemental in International but got removed (but might bring it back).
Add options from NumberRangeFormatter to this modules :woman_shrugging: Haven’t touched the API yet.

ECMA 402: Intl.NumberFormat v3

Features Status Notes
Rounding modes :heavy_check_mark:
Enumerated "useGrouping" option :heavy_check_mark:
roundingIncrement option :x: Can’t find a use case here.
Interpreting strings as decimal :heavy_check_mark:

Other suggestions

Feature Status Notes
Change the default compact rounding :woman_shrugging: The default seems to work, but most other number abbreviation system does it differently
Change the default compact pattern :woman_shrugging: Suffixes from Miner’s Haven works, unlikely but we’ll see.
Option to change the minimumGroupingDigits :x: (for values over 4), :woman_shrugging: (for 3 and 4), :heavy_check_mark: (for 1 and 2) Can’t find a case where 1 or 2 is not the answer. You can use useGrouping = "min2" for it to be 2 and "always" for it to be 1. Might add an option to set it to 3 or 4 (through "min3" and "min4" value for the useGrouping option) but we’ll see.
NaN and Infinity symbol option :woman_shrugging:
Abbreviations fallback to scientifc notation if there isn’t any available :heavy_check_mark: MoneyLib does this but I can’t find a use case for this
Custom number patterns :woman_shrugging: Does anyone use FormatCustom in the previous version of FormatNumber?
Option argument respect the __index metamethod if the table has it :woman_shrugging: Unlikely but if there are cases, I’ll add this.
Option to change "0" pattern rounding behaviour :soon: Yep most abbreviation module rounds it differently when it the special "0" pattern. Usually rounding down to the nearest integer for "0" patterns.
3 Likes

Update 2.2 upcoming
Here are the upcoming features:

More rounding options for FormatCompact

Experemental, might change in the future
Now with minimum signfiicant digits to keep and trailing zeroes if rounded
{ minimumSignificantDigitsToKeep = 3 } → 1.23 12.3 123 1234 12,345 123,456
{ trailingZeroesIfRounded = 1 } → 1.0 1.2 10 12 100 123 1000 1234 10,000 12,345 100,000 123,456

End fallback

You can now fallback if the end doesn’t have any abbreviations available.
Whether be like MoneyLib and fallback to scientific notation.
You have three options of fallbacks:

  • Last abbreviation with more digits added (default)
  • Scientific notation (10 ^ 309 and 10 ^ 310 returns 1E309 and 1E310 instead of 1000 UNCENT and 10,000 UNCENT)
  • Standard notation (can be solved by adding "0" at the end)

Scientific notation

FormatScientific function added, with an option of 1E1 or 1e1 defaulting to 1E1.

Minor changes:

  • useGrouping now accepts booleans. true is "always" for FormatStandard and "min2" for FormatCompact and false is "never"

Release is upcoming.
(Random tirival info: The option argument doesn’t respect the __index metamethod :see_no_evil:)

1 Like

How does one go about this ie. 123,456.7890 into → 123,456 as seen here with this gatekeeper boss UI.

Sorry, I’m not much of a documentation person --I did try reading it though, and looking through the thread but couldn’t get what I wanted to achieve, although I saw the first reply placing it in didn’t work. :stuck_out_tongue:

P.S. For a higher level boss I was trying to make it display as 30.1M / 59.99M (or 25M / 59.99M) so how would I’d go about doing that too (using rounding), thanks for the this anyways. :+1:

1 Like

The maximum fraction digits does this, as it looks like you want to truncate the fractional digit with rounding mode set to "down".
(or you could use math.floor if you want to round down the value before formatting as well)

2 Likes

2.2 released, you can get it here: FormatNumber.rbxm (8.9 KiB)

Added feautres:

  • More compact rounding options, the default is the same as before
  • Scientific notation.
  • useGrouping boolean implicit conversion, true = “always” / “min2” for compact notation, false = “never”.

Update 2.3 planned features

The features I’m plannning to add in the next update.

Different numbering systems support

From 𝟏𝟐𝟑𝟒𝟓𝟔𝟕𝟖𝟗 to 一二三四五六七八九 to ١٢٣٬٤٥٦٬٧٨٩. Here are the list that are planned to be supported:

Code Numbering system
latn Western Digits (default)
arab Arabic-Indic Digits
beng Bangla Digits
tibt Tibetan Digits
arabext Extended Arabic-Indic Digits
deva Devanagari Digits
mymr Myanmar Digits
olck Ol Chiki Digits
hanidec Chinese Decimal Numerals
thai Thai Digits
tamldec Tamil Digits

Format to parts

A part formatting in “ECMA 402 style”, similar to Intl.NumberFormat.formatToParts (ECMA 402) and International.NumberFormat:FormatToParts (International).


to

{
	{ type = "currency", value = "¤" },
	{ type = "literal", value = " " },
	{ type = "integer", value = "12" },
	{ type = "group", value = "," },
	{ type = "integer", value = "345" },
	{ type = "decimal", value = "." },
	{ type = "fraction", value = "68" },
	{ type = "literal", value = " " },
	{ type = "compact", value = "T" }
}

Better range formatting API

Range formatting option based on Unicode ICU, will be experemental, options:

rangeIdentityFallback
The behaviour when two numbers are similar after it had been rounded:

  • "singleValue" show it as a single value rather than the range (default)
  • "approximately" show the value using approximation symbol
  • "approximatelyOrSingleValue"show the value using approximation symbol expect if the numbers are the same before it was rounded, which shows it as a single value instead.
  • "range" show the number in range

rangeCollapse
Collapse the range by notation level, can either be true or false (or nil), defaults to false

print(FormatNumber.FormatCompactRange(1000, 2000, { rangeCollapse = true })) --> 1–2k
print(FormatNumber.FormatScientificRange(1000, 2000, { rangeCollapse = true })) --> 1–2E3

Note
Format range functions will also return 2 values, the first is the formatted and the second returns either of these three value:

  • "notEqual" two numbers in the range doesn’t equal to each other
  • "equalAfterRounding" two numbers in the range equals to each other after it was rounded
  • "equalBeforeRounding" two numbers in the range equals to each other even before it was rounded
4 Likes

Update 2.3

The rangeCollapse option are now the following and no longer booleans as planned:

  • "none" never collapse (default)
  • "unit" collapse range by unit level (currency, and percent)
  • "all" collapse range by notation and unit level.

(FormatCompactRange will not return 2 value now because it isn’t easy to implement, it might in the future)

File:
FormatNumber.rbxm (12.3 KiB)

Why formatting to parts?

While it’s more useful and there are more use cases in International, this still have a use without it e.g. decorate certain part. (For example 1.5k instead of 1.5k). Implementing it yourself isn’t easy and can be a mess.
International has this so you can customise formatted strings while preserving locale-based components (espacially decimal and grouping symbols).
It might replace decimalSymbol and groupSymbol in the future.

How does the FormatCompact work?

It’s based on powers of 10 that gets the pattern depending on the power of 10 with 0 as the size.
I made a mistake by scaling it (depending on the size of the 0) then the rounding it when I’ve should’ve gone signfiicant digit rounding first, then I substitute the 0 with. I also take grouping into consideraton as it’s just a scaled-down number.
If the pattern is a single 0 without any other characters ("0") it won’t scale the number.
International also takes plural rules into account.

E.g. The number is 1,234,567

  1. Get the length of it (and remove leading zeroes first), the length is 7.
  2. Get the 7th value of the pattern (let’s say the 7th pattern is 0000K)
  3. Check if that pattern equals to "0" if so skip to step 4 and ignore step 5 otherwise scale the value so it’ll show 4 digits (because the size of 0 is 4) so it’ll be 1234.567
  4. Format that value by itself so 1234.567 becomes 1,234.56 (assuming rounding by 2 decimal places and grouping strategy is "always").
  5. Substitute the zero so that 0000K becomes 1,234.56K

So the output would be 1,234.56K.
(In reality, it’s more complex than that as it also checks to see if the value rounded to a value with a digit higher than the original value if so re-scale it, and for International plural rules etc)

1 Like

Bugs

Description Fixed on international version Fixed on FormatNumber version
Compact notation/abbreviation rounding error (e.g. 1,000,000 returns 1000K) 2.4.0 2.1.0
Sign display exceptZero error for NaN and -0 2.6.0 (not released) ~
Scientific notation for 0 fixed 2.6.0 2.2.0
Rounding fixed 2.5.0 2.1.0
min2 grouping strategy now preserved the minimum grouping digits value if > 2 2.4.0 Never happend here
Date formatting option fix (when the month option) 2.5.1 ~
Locale system bug 2.6.0, 2.5.0 (variants) ~
Very small numbers (like 1e-308) returns 0 for doubles 2.6.0 Not yet fixed
0 counted as significant digits 2.2.0 Never happened
Signficant digits doesn’t respect decimals 2.5.0 2.1.0
RelativeTimeFormat doesn’t respect the fraction/integer/signfiicant digits option and defauts to auto instead of min2 for grouping in compact notation 2.6.0 ~
ListFormat bug when inserted “{0}”/“{1}” 2.5.1 ~
ListFormat FormatToParts errors 2.5.0 ~

If you find more bugs in both of the modules, please let me know.
I will (probably) not be releasing any more feature changes (for both FormatNumber and International) until CLDR 38. The only change I’ll (probably) make is bug fixes.

1 Like

Question, whats the difference between this and using international for number formatting?

The name literally says it International.
International 2.x is locale-based with OOP (You had to create a number formatter object) and is much harder to implement.
FormatNumber is actually older (version 1 is based on .NET’s API, version 2 is ECMA-402 based API aside from notation being split into multiple methods because it seemed more sense back when I designed the API for 2.0).
FormatNumber doesn’t use CLDR data although compact notation patterns are based around it.
I do not implement OOP for this module (FormatNumber) because it complicates the module exponentially.
FormatToParts already made it too complex and I might remove it in the future for this module.
Another motivation is the size of International (~9 MiB) is too large, I won’t and can’t make it any more smaller, removing all locale datas but en is “pointless” as the goal is to get localized result and imo contradicts the purpose of International so I made version 2 of FormatNumber.
I also have more “freedom” for FormatNumber, I won’t insert

I recommend International if:

  • Have a strong understanding of the ICU or JavaScript’s Intl API.
  • Have some understanding of CLDR
  • Your game needs to be localised
  • You don’t mind subtle implemention details.

I recommend FormatNumber if:

  • You’re a less expereinced programmer (it’s more beginner-friendly)
  • Your game don’t need to be localised
  • You find that International is too heavyweighted.
  • You don’t understand what OOP is

International can work without number formatting.

Oh, someone showed me how to format numbers with International anyways, ill stick with that

I haven’t read sufficiently into the original post to determine an answer - but for the locale-aware version, have you implemented Vedic digit grouping (1,00,00,000 = 1 crore) and the myriad system in East Asia (1,0000,0000 = 1亿 / 1億). I noticed a some hints of the myriad system in a few diagrams, but there wasn’t any mention of these groupings explicitly.

There is myriad compact notation (e.g. 1万) but there isn’t a myraid digit grouping (no locale have myraid grouping including the east asian locale) and there’s vedic digit grouping (e.g. 1,23,456) but not vedic compact notation outside of currency (e.g. 1 lakh) until IIRC CLDR 39.

I only needed to deal with two (previously three) different grouping size (thousands [3, 3], lakhs/crores[3, 2], ceb percent until CLDR 38 [2, 2]), although International can handle any grouping size with [x, y] in the format of ...y,y,y,x (e.g. [4, 3] is 100,000,000,0000).

Do you have a use case for myriad grouping sizes, East Asian locales seems to use thousands for grouping sizes?

1 Like

If you look in Wikipedia (or even any website that relays the basics of Mandarin), you’ll see otherwise.

Neither of the page mentions the grouping size being [4, 4], it only mentioned compact notation in myraids?

File a bug report if you disagree the zh locale standard decimal formatting being #,##0.###:
https://st.unicode.org/cldr-apps/v#/zh/Number_Formatting_Patterns/24a93b3d14ba17b2

3.0.0 update

Completely remade the module.
You can safely ignore many of my old statement, these no longer apply in version 3, things have been changed.
I based it around the ICU’s NumberFormatter API and simplified the module, removing features that complicates the implementation (formatting to parts, number range formatting) with not many use cases outside of i18n.

Why NumberFormatter class?

There isn’t any reason behind it, just a design decision and doesn’t really make the module more complicated. I’d say it’d make the implementation easier as it doesn’t have to resolve options and check types every time the function calls.
This way, you can have multiple formatters with different settings. It’s easier to change settings this way.

Old post

I’ve remade this module. With more user-friendly functions, and it’s easy to use, just call the function with the value as the argument, with an optional option argument if you’re not satsified with the default!

2.3.0
FormatNumber.rbxm (12.3 KB)

2.2.0
FormatNumber.rbxm

2.1.0
FormatNumber.rbxm (7.8 KB)

2.0.1
FormatNumber.rbxm (7.3 KB)

2.0.0
FormatNumber.rbxm (7.3 KB)

Features

  • Negaive number, decimal, infinity and NaN support.
  • BigNum/BigInt and numeric string support
  • Range formatting
  • Formatting to parts.

Does not include

  • Unit formatting.
  • Pluralised number abbreviation.
  • Currency names

Functions

string FormatNumber.FormatStandard(number/BigNum/BigInt value, table options)
Format numbers in the standard pattern.

Example

print(FormatNumber.FormatStandard(1234.56)) --> 1,234.56
print(FormatNumber.FormatStandard(-1234.56)) --> -1,234.56
print(FormatNumber.FormatStandard(0/0)) --> NaN

string FormatNumber.FormatCompact(number/BigNum/BigInt value, table options)
Want to abbreviate numbers? No problem. Uses @berezaa’s suffixes (MoneyLib) and up to 10^308.

Example

print(FormatNumber.FormatCompact(1234)) --> 1.2k
print(FormatNumber.FormatCompact(12345)) --> 12k

string FormatNumber.FormatScientific(number/BigNum/BigInt start_value, number/BigNum/BigInt, end_value, table options)
Show numbers in scientific notation. Supports engineering

string, string FormatNumber.FormatStandardRange(number/BigNum/BigInt start_value, number/BigNum/BigInt end_value, table options)
string FormatNumber.FormatCompactRange(number/BigNum/BigInt start_value, number/BigNum/BigInt end_value, table options)
string, string FormatNumber.FormatScientificRange(number/BigNum/BigInt start_value, number/BigNum/BigInt end_value, table options)
Format numbers in range, experimental. (Expect for FormatCompactRange which only returns 1 value (don’t ask), it returns 2 value, the 1st is the formatted value while the 2nd is the rounding result)

print((FormatNumber.FormatStandardRange(1234, 12345))) --> 1,234–12,345
print((FormatNumber.FormatStandardRange(-math.huge, math.huge))) --> -∞–∞
print((FormatNumber.FormatCompactRange(1000, 2000))) --> 1k–2k

table FormatNumber.FormatStandardToParts(number/BigNum/BigInt value, table options)
table FormatNumber.FormatCompactToParts(number/BigNum/BigInt value, table options)
table FormatNumber.FormatScientificToParts(number/BigNum/BigInt value, table options)
Format numbers to parts, experimental.

type meaning
integer The integral part of the value
decimal The decimal symbol
group The grouping symbol
fraction The fraction part of the value
minusSign The minus sign
plusSign The plus sign
currency The currency value
literal The literal value
nan The Not-a-Number value
infinity The infinity value

table Format
Number
.AbbreviationToCLDR(table abbreviations, boolean include_currency)
Converts abbreviation suffixes of 3 digits to Unicode CLDR compact number pattern so you can use it on compactPattern as that only accept that “CLDR”-styled pattern (no plurals though).

Example FormatNumber.AbbreviationsToCLDR{'k', 'M', 'B', 'T'} converts it to {'0k', '00k', '000k', '0M', '00M', '000M', '0B', '00B', '000B', '0T', '00T', '000T'}

Options

Applies to FormatStandard and FormatCompact
groupSymbol
The grouping symbol, the default is ,

decimalSymbol
The decimal symbol, the default is .

useGrouping
Determine the number should be grouped. This modules assumes the default minimum grouping digits is 1 so:

  • "always" group the number (default for FormatStandard) (Trivial info: It also ignores locales that disables grouping like bg currency and the en-US-POSIX locale and still group the number)
  • "min2" group the number only if it has 5 digits or over (default for FormatCompact) (Trivial info: The actual function is locale dependant and it actually means the minimum grouping digits will be overrided to 2 if it’s lower than 2, so if the default minimum grouping digits is 3 like locale ee or 4 like locale hu before CLDR 36, it still won’t group values below 6 digits, this info does not matter here and this can be safely ignored)
  • "never", don’t group the number

Trivial info: The "auto" value isn’t supported because that’s locale dependant, and is redundant because the default minimum grouping digits is assumed to be 1 and “always” sets the minimum grouping digits to 1

style
The formatting style to use

  • "decimal" plain number formatting
  • "currency" currency number formatting
  • "percent" percent formatting

Trivial info: The "unit" value isn’t supported because it doesn’t support unit formatting

currency
The currency to format, (For this module, this is a currency symbol, while in International, this is the ISO 4217 currency code)

rounding
Rounding types

  • "halfEven" rounds to the nearest even in when it’s halfway or over (default)
  • "halfUp" rounds up the value when it’s halfway or over
  • "halfDown" rounds down the value when it’s halfway or over
  • "down" rounds down the value
  • "up" rounds up the value

only available on FormatCompact and FormatCompactRange
compactPattern
The compact pattern in tables, it starts at thousands so if the value is 1000 and the pattern is {'0K'}, it’ll format it as 1K

The pattern string is based around Unicode CLDR’s, ; for separation of positive and negative, ¤ for currency placeholder, etc. Keep in mind 0 fallbacks to FormatStandard and any value below 1000 have a pattern of 0 and only the 0 (size) and literal pattern (’) are suppored.
For example if I insert the value of 12345

pattern formatted
0 12,345
0 ten thousand 1.2 ten thousand
00k 12k

The default is the abbreviation pattern is ber’s Miner Haven, it’ll format values similarly to MoneyLib (except that values over 10^309 won’t be in scientific notation)

If at least one of the minimumSignificantDigits and maximumSignificantDigits option is not nil, minimumFractionDigits, maximumFractionDigits, minimumIntegerDigits and maximumIntegerDigits are ignored, and (Only applies to FormatCompact and FormatCompactRange) if at least one of the minimumSignificantDigits, maximumSignificantDigits, minimumFractionDigits, maximumFractionDigits, minimumIntegerDigits and maximumIntegerDigits option is not nil, minimumSignificantDigitsToKeep and trailingZeroesIfRounded are ignored.

minimumFractionDigits
The minimum of fractional digit to use, defaults to 0 (unlike International.NumberFormat which defaults depending on the ISO 4217 currency entered if the style is currency, this still defaults to 0 if the style is currency)

maximumFractionDigits
The maximum of fracitonal digit to use, defaults to 3, use math.huge for unlimited maximum fraciton digits.

minimumIntegerDigits
The minimum of integral digits to use (Zero padded), for example if the minimum integer digit is 2 and 1 is entered, it’ll format it as 01, defaults to 1

maximumIntegerDigits
(undocumented)

minimumSignificantDigits
The minimum of significant digits to use.

maximumSignificantDigits
The maximum of significant digits to use.

experemental
only available on FormatCompact and FormatCompactRange
minimumSignificantDigitsToKeep
The minimum significant digits to keep, and don’t round those, defaults to 2.

only available on FormatCompact and FormatCompactRange
trailingZeroesIfRounded
The minimum trailing zeroes if the FormatCompact/FormatCompactRange is rounded, defaults to 0.

Example
value trailingZeroesIfRounded minimumSignificantDigitsToKeep rounded/trauncated
1 0 2 1
1.2 0 2 1.2
9.87 0 2 9.8
10 0 2 10
12.3 0 2 12
98.76 0 2 98.7
100 0 2 100
123.4 0 2 123
987.65 0 2 987
1000 0 2 1000
1234.5 0 2 1234
9876.54 0 2 9876
10,000 0 2 10,000
98,765.43 0 2 98,765
12,345.6 0 2 12,345
1 0 3 1
1.2 0 3 1.2
9.87 0 3 9.87
10 0 3 10
12.3 0 3 12.3
98.76 0 3 98.7
100 0 3 100
123.4 0 3 123
987.65 0 3 987
1000 0 3 1000
1234.5 0 3 1234
9876.54 0 3 9876
10,000 0 3 10,000
98,765.43 0 3 98,765
12,345.6 0 3 12,345
1 1 2 1.0
1.2 1 2 1.2
9.87 1 2 9.8
10 1 2 10
12.3 1 2 12
98.76 1 2 98.7
1 2 3 1.00
1.2 2 3 1.20
9.87 2 3 9.87
10 2 3 10.0
12.3 2 3 12.3
98.76 2 3 98.7
100 2 3 100
123.4 2 3 123
987.65 2 3 987
1 1 3 1.0
1.2 1 3 1.2
9.87 1 3 9.87
10 1 3 10
12.3 1 3 12.3
98.76 1 3 98.7

Only available on FormatScientific and FormatScientificRange
engineering
Show in exponent in 10s only when it’s divisble by three, defaults to false

exponentLowercased
experemental, might change
Shows the exponent symbol as e instead of E, defaults to false

Question

Is it really easy to use?

Yep, all you need to is just call the function, with the value argument and if you’re not happy you can create a dictionary for the option argument with options you can change.

print(FormatNumber.FormatStandard(1000)) --> 1,000
print(FormatNumber.FormatCompact(1234)) --> 1.2k

Why was min2 the default value for useGrouping for numbers abbreviations?

International originally have two options for grouping: true and false, true maps to "auto" and false maps to "never" for standard notation however true maps to "min2" for compact notation/number abbreviation, the reason for this is was back then I was trying to replicate ECMA 402 behaviour. On the 2.1 update, I added more grouping options, and min2 became the default for grouping for compact notation and that’s the hang over from it.
You might also notice ECMA 402 also default min2 as grouping for compact notation (and still uses booleans for useGrouping option):
image
ECMA 402 does this because Unicode ICU defaulting grouping for compact notation to be min2.

That’s the way it is and it had always been that way. In summary, the behaviour is a hangover from International which is a hangover from ECMA 402 which uses Unicode ICU default grouping for compact notation.

Is this locale-aware?

No. If you want a locale aware version, see International. This is a subset of International so it might feel similar.

2 Likes

Sounds like something many people with stats systems would use. I hope this gets updated more in the future.

Fantastic work.
This is incredible, i’ve tried a few solutions for number formatting but they all seem to fail after 100 trillion.

Thank you very much.

I remember using this module at around versions 2.0.0 and up, and it was very useful. I came back to check for updates recently, and in my opinion, it’s gotten incredibly more complex to use after versions 3.0.0+. I’m sure people have their use cases, but as an average developer, the newer versions are not for me.

1 Like

yeah, i’d much rather use the old ones. FormatCompact felt a lot easier than, whatever we do now

1 Like

(This has been superseded by the Simple API though this is not deprecated and is here for backwards compatibility - I’ll still provide bug fixes for now but no new features will likely be added)

I decided to create a separate API that doesn’t contain NumberFormatter class if that’s not your thing.
This is slightly simpler with one function call rather than creating class than call the format method.
The alternative API will be just as supported as the NumberFormatter API.
It loses many features with use cases, but if you do not need it, you might prefer this over the NumberFormatter API.

All functions support negative numbers and all functions except FormatInt supports pretty much every number (including decimals).

You would need to use the files provided to use the alternative API
Alternatively, I’ve uploaded a model:FormatNumber (Old Alternative API) - Roblox

Module

3.0.0b3

File FormatNumberAlt 3.0.0b3.rbxm (28.4 KiB)

3.0.0b2

File: FormatNumber Alt 3.0.0b2.rbxm (28.0 KiB)

3.0.0b1

File: FormatNumber Alt 3.0.0b1.rbxm (27.9 KiB)

API

All of these function formats so the integer part of the formatted number are separated by the grouping separator every 3 digits.

function FormatNumber.FormatInt(value: number): string
Formats an integer.

function FormatNumber.FormatStandard(value: number): string
Formats a number.

function FormatNumber.FormatFixed(value: number, digits: number?): string
Formats a number rounded to the certain decimal places.
The default is 6 decimal places.

function FormatNumber.FormatPrecision(value: number, digits: number?): string
Formats a number rounded to the certain significant digits.
The default is 6 significant digits.

function FormatNumber.FormatCompact(value: number, fractionDigits: number?): string
Formats a number so it is in compact form (abbreviated such as “1000” to “1K”).
The significand (referring to 1.2 in “1.2K”) is truncated to the fractionDigits specified in the argument. If not, it is truncated to integers but keeping 2 significant digits.
You can change the suffix by changing the compactSuffix field from the config ModuleScript included in the module.

4 Likes