nc.num
Numbers: clamping, rounding that gets decimals right, statistics, and formatting for humans (sizes, money, ordinals, compact numbers) in any language. Formatting is English by default: change it with setLocale() or per call with { locale }.
const { num } = require("@ix-xs/node-comfort");
import { setLocale } from "@ix-xs/node-comfort/num";num.round(1.005, 2); // 1.01
num.formatBytes(1536); // "1.5 KB"
num.currency(1234.5, "EUR", { locale: "fr" }); // "1 234,50 €"
num.percentile(latencies, 95);nc.num.Functions
nc.num.setLocale()
setLocale(locale: string): typeof nc.numSets the default language of format, currency, percent, abbreviate, ordinal and formatBytes.
Parameters
| Name | Type | Description |
|---|---|---|
locale | string | Like "fr", "en-GB" or "pt-BR". |
Returns typeof import("./Num"): The module, so calls chain.
Example
num.setLocale("fr");
num.currency(1234.5, "EUR"); // "1 234,50 €"nc.num.getLocale()
getLocale(): stringThe current default language.
Returns string
Example
num.getLocale(); // "en"nc.num.clamp()
clamp(value: number, min: number, max: number): numberKeeps a number between min and max.
Parameters
| Name | Type |
|---|---|
value | number |
min | number |
max | number |
Returns number
Example
num.clamp(150, 0, 100); // 100
num.clamp(-5, 0, 100); // 0nc.num.inRange()
inRange(value: number, min: number, max: number): booleanIs the number between min and max, both included?
Parameters
| Name | Type |
|---|---|
value | number |
min | number |
max | number |
Returns boolean
Example
num.inRange(10, 0, 10); // truenc.num.wrap()
wrap(value: number, min: number, max: number): numberWraps a number around a range, like an angle or a carousel index. max is excluded.
Parameters
| Name | Type |
|---|---|
value | number |
min | number |
max | number |
Returns number
Example
num.wrap(370, 0, 360); // 10
num.wrap(-1, 0, 5); // 4nc.num.round()
round(value: number, decimals?: number): numberRounds to decimals places without floating-point surprises: Math.round(1.005 * 100) / 100 gives 1, this gives 1.01. Halves round away from zero, like in a spreadsheet.
Parameters
| Name | Type | Description |
|---|---|---|
value | number | |
decimalsoptional | number | Negative values round to tens, hundreds...Default: 0 |
Returns number
Example
num.round(1.005, 2); // 1.01
num.round(1234, -2); // 1200
num.round(-2.5); // -3nc.num.floor()
floor(value: number, decimals?: number): numberRounds down to decimals places.
Parameters
| Name | Type | Description |
|---|---|---|
value | number | |
decimalsoptional | number | Default: 0 |
Returns number
Example
num.floor(1.789, 2); // 1.78nc.num.ceil()
ceil(value: number, decimals?: number): numberRounds up to decimals places.
Parameters
| Name | Type | Description |
|---|---|---|
value | number | |
decimalsoptional | number | Default: 0 |
Returns number
Example
num.ceil(1.231, 2); // 1.24nc.num.snap()
snap(value: number, step: number): numberRounds to the nearest multiple of step.
Parameters
| Name | Type |
|---|---|
value | number |
step | number |
Returns number
Example
num.snap(17, 5); // 15
num.snap(0.37, 0.25); // 0.25nc.num.approxEqual()
approxEqual(a: number, b: number, epsilon?: number): booleanAre two numbers equal within a small tolerance? The right way to compare float results, since 0.1 + 0.2 === 0.3 is false.
Parameters
| Name | Type | Description |
|---|---|---|
a | number | |
b | number | |
epsilonoptional | number | Allowed difference, relative to the size of the numbers.Default: Number.EPSILON * 16 |
Returns boolean
Example
num.approxEqual(0.1 + 0.2, 0.3); // truenc.num.lerp()
lerp(start: number, end: number, t: number): numberThe value at ratio t between start and end.
Parameters
| Name | Type | Description |
|---|---|---|
start | number | |
end | number | |
t | number | Usually between 0 and 1. |
Returns number
Example
num.lerp(0, 100, 0.25); // 25nc.num.mapRange()
mapRange(value: number, inMin: number, inMax: number, outMin: number, outMax: number): numberMoves a number from one range to another, keeping its relative position.
Parameters
| Name | Type |
|---|---|
value | number |
inMin | number |
inMax | number |
outMin | number |
outMax | number |
Returns number
Example
num.mapRange(5, 0, 10, 0, 100); // 50
num.mapRange(75, 0, 100, 1, 0); // 0.25nc.num.random()
random(min?: number, max?: number): numberA random float from min (included) to max (excluded). Not for security: it uses Math.random.
Parameters
| Name | Type | Description |
|---|---|---|
minoptional | number | Default: 0 |
maxoptional | number | Default: 1 |
Returns number
Example
num.random(10, 20); // 13.84...nc.num.randomInt()
randomInt(min: number, max: number): numberA random integer from min to max, both included. Not for security.
Parameters
| Name | Type |
|---|---|
min | number |
max | number |
Returns number
Example
num.randomInt(1, 6); // a dice rollnc.num.sum()
sum(values: Iterable<number>): numberAdds up numbers.
Parameters
| Name | Type |
|---|---|
values | Iterable<number> |
Returns number
Example
num.sum([1, 2, 3]); // 6nc.num.average()
average(values: Iterable<number>): numberThe mean, or 0 for an empty list.
Parameters
| Name | Type |
|---|---|
values | Iterable<number> |
Returns number
Example
num.average([2, 4, 9]); // 5nc.num.median()
median(values: Iterable<number>): numberThe middle value once sorted, or 0 for an empty list.
Parameters
| Name | Type |
|---|---|
values | Iterable<number> |
Returns number
Example
num.median([3, 1, 2]); // 2
num.median([1, 2, 3, 4]); // 2.5nc.num.mode()
mode(values: Iterable<number>): number[]The most frequent values.
Parameters
| Name | Type |
|---|---|
values | Iterable<number> |
Returns number[]
Example
num.mode([1, 1, 2, 2, 3]); // [1, 2]nc.num.variance()
variance(values: Iterable<number>, options?: VarianceOptions): numberThe variance: the average squared distance from the mean.
Parameters
| Name | Type |
|---|---|
values | Iterable<number> |
optionsoptional | VarianceOptions |
Returns number
Example
num.variance([2, 4, 4, 4, 5, 5, 7, 9]); // 4nc.num.stdDev()
stdDev(values: Iterable<number>, options?: VarianceOptions): numberThe standard deviation.
Parameters
| Name | Type |
|---|---|
values | Iterable<number> |
optionsoptional | VarianceOptions |
Returns number
Example
num.stdDev([2, 4, 4, 4, 5, 5, 7, 9]); // 2nc.num.percentile()
percentile(values: Iterable<number>, p: number): numberThe value under which p percent of the values fall, interpolated like Excel's PERCENTILE.INC.
Parameters
| Name | Type | Description |
|---|---|---|
values | Iterable<number> | |
p | number | From 0 to 100. |
Returns number: NaN for an empty list.
Example
num.percentile([1, 2, 3, 4, 5], 90); // 4.6
num.percentile(responseTimes, 95); // p95 latencync.num.min()
min(values: Iterable<number>): number | undefinedThe smallest number. Unlike Math.min(...array), huge arrays are fine.
Parameters
| Name | Type |
|---|---|
values | Iterable<number> |
Returns number | undefined: undefined for an empty list.
nc.num.max()
max(values: Iterable<number>): number | undefinedThe largest number. Unlike Math.max(...array), huge arrays are fine.
Parameters
| Name | Type |
|---|---|
values | Iterable<number> |
Returns number | undefined: undefined for an empty list.
nc.num.percent()
percent(value: number, total: number, decimals?: number): numberWhat percentage value is of total. Returns 0 when total is 0.
Parameters
| Name | Type | Description |
|---|---|---|
value | number | |
total | number | |
decimalsoptional | number | Default: 2 |
Returns number
Example
num.percent(25, 200); // 12.5
num.percent(1, 3, 1); // 33.3nc.num.gcd()
gcd(...values: number[]): numberGreatest common divisor.
Parameters
| Name | Type |
|---|---|
...values | ...number |
Returns number
Example
num.gcd(12, 18, 27); // 3nc.num.lcm()
lcm(...values: number[]): numberLeast common multiple.
Parameters
| Name | Type |
|---|---|
...values | ...number |
Returns number
Example
num.lcm(2, 3, 4); // 12nc.num.isPrime()
isPrime(value: number): booleanIs it a prime number?
Parameters
| Name | Type |
|---|---|
value | number |
Returns boolean
Example
num.isPrime(7); // true
num.isPrime(1); // falsenc.num.factorial()
factorial(n: number, asBigInt?: boolean): number | bigintn!. Pass true to get an exact bigint, since numbers lose precision past 18!.
Parameters
| Name | Type | Description |
|---|---|---|
n | number | |
asBigIntoptional | boolean | Default: false |
Returns number | bigint
Throws RangeError If n is negative or not an integer.
Example
num.factorial(5); // 120
num.factorial(25, true); // 15511210043330985984000000nnc.num.isEven()
isEven(value: number): booleanIs it even?
Parameters
| Name | Type |
|---|---|
value | number |
Returns boolean
nc.num.isOdd()
isOdd(value: number): booleanIs it odd? Negative numbers work too.
Parameters
| Name | Type |
|---|---|
value | number |
Returns boolean
nc.num.range()
range(start: number, end?: number, step?: number): number[]Numbers from start up to end (excluded). With one argument, counts from 0. Goes down when end is smaller.
Parameters
| Name | Type | Description |
|---|---|---|
start | number | |
endoptional | number | |
stepoptional | number | Defaults to 1, or -1 when counting down. |
Returns number[]
Example
num.range(4); // [0, 1, 2, 3]
num.range(0, 10, 2); // [0, 2, 4, 6, 8]
num.range(5, 0); // [5, 4, 3, 2, 1]nc.num.parse()
parse(value: unknown, fallback?: number): numberReads a number from anything, ignoring trailing text like units.
Parameters
| Name | Type | Description |
|---|---|---|
value | unknown | |
fallbackoptional | number | Returned when there's no number to read.Default: NaN |
Returns number
Example
num.parse("42px"); // 42
num.parse(" -3.5 kg"); // -3.5
num.parse("nope", 0); // 0nc.num.parseBytes()
parseBytes(value: string | number, options?: ParseBytesOptions): numberTurns a size like "10 MB" into bytes. The opposite of formatBytes().
Parameters
| Name | Type | Description |
|---|---|---|
value | string | number | A size like "512kb" or "1.5G", or a number of bytes. |
optionsoptional | ParseBytesOptions |
Returns number: Bytes, or NaN if it can't be read.
Example
num.parseBytes("1.5 KB"); // 1536
num.parseBytes("2 GiB"); // 2147483648
num.parseBytes("1 KB", { binary: false }); // 1000nc.num.formatBytes()
formatBytes(bytes: number, options?: FormatBytesOptions): stringFormats a byte count as a readable size.
Parameters
| Name | Type |
|---|---|
bytes | number |
optionsoptional | FormatBytesOptions |
Returns string
Example
num.formatBytes(1536); // "1.5 KB"
num.formatBytes(1000, { binary: false }); // "1 KB"
num.formatBytes(1536, { locale: "fr", units: ["o", "Ko", "Mo", "Go"] }); // "1,5 Ko"nc.num.format()
format(value: number | bigint, options?: FormatNumberOptions): stringFormats a number for display, with Intl.NumberFormat doing the work: separators, decimals, compact notation, percentages, units.
Parameters
| Name | Type |
|---|---|
value | number | bigint |
optionsoptional | FormatNumberOptions |
Returns string
Example
num.format(1234567.891); // "1,234,567.891"
num.format(1234567.891, { locale: "fr" }); // "1 234 567,891"
num.format(0.256, { style: "percent" }); // "26%"
num.format(1500, { compact: true }); // "1.5K"
num.format(3.5, { unit: "kilometer" }); // "3.5 km"nc.num.currency()
currency(value: number | bigint, code: string, options?: CurrencyOptions): stringFormats an amount of money.
Parameters
| Name | Type | Description |
|---|---|---|
value | number | bigint | |
code | string | A currency code like "EUR", "USD" or "JPY". |
optionsoptional | CurrencyOptions |
Returns string
Example
num.currency(1234.5, "USD"); // "$1,234.50"
num.currency(1234.5, "EUR", { locale: "fr" }); // "1 234,50 €"
num.currency(-5, "USD", { accounting: true }); // "($5.00)"nc.num.abbreviate()
abbreviate(value: number, decimals?: number): stringShortens big numbers with K, M, B or T. For other languages, use format(value, { compact: true, locale }).
Parameters
| Name | Type | Description |
|---|---|---|
value | number | |
decimalsoptional | number | Default: 1 |
Returns string
Example
num.abbreviate(1500); // "1.5K"
num.abbreviate(2_400_000); // "2.4M"nc.num.thousands()
thousands(value: string | number, separator?: string): stringAdds thousands separators, leaving decimals alone.
Parameters
| Name | Type | Description |
|---|---|---|
value | number | string | |
separatoroptional | string | Default: "," |
Returns string
Example
num.thousands(1234567.89, " "); // "1 234 567.89"nc.num.ordinal()
ordinal(value: number, options?: OrdinalOptions): stringAdds the ordinal suffix: 1st, 2nd, 3rd... in several languages.
Parameters
| Name | Type |
|---|---|
value | number |
optionsoptional | OrdinalOptions |
Returns string
Example
num.ordinal(22); // "22nd"
num.ordinal(1, { locale: "fr" }); // "1er"
num.ordinal(3, { locale: "de" }); // "3."Types
Import any of them in TypeScript with import type { CurrencyOptions } from "@ix-xs/node-comfort", or in JavaScript with import("@ix-xs/node-comfort").CurrencyOptions.
CurrencyOptions
Options for currency().
| Property | Type | Description |
|---|---|---|
localeoptional | string | Language. Defaults to the one set with setLocale(), or "en". |
decimalsoptional | number | Defaults to the currency's usual decimals (2 for EUR, 0 for JPY). |
displayoptional | "symbol" | "code" | "name" | "narrowSymbol" | €, €, EUR or euros. Defaults to "symbol". |
accountingoptional | boolean | Show negative amounts in parentheses, like ($5.00). |
FormatBytesOptions
Options for formatBytes().
| Property | Type | Description |
|---|---|---|
decimalsoptional | number | Maximum decimals. Defaults to 1. |
binaryoptional | boolean | 1 KB is 1024 bytes when true, 1000 when false. Defaults to true. |
iecoptional | boolean | Use KiB, MiB, GiB labels. |
localeoptional | string | Formats the number for a language, like "fr" for "1,5 KB". |
unitsoptional | string[] | Your own labels from bytes up, like ["o", "Ko", "Mo", "Go", "To"]. |
FormatNumberOptions
Options for format().
| Property | Type | Description |
|---|---|---|
localeoptional | string | Language, like "fr" or "en-US". Defaults to the one set with setLocale(), or "en". |
decimalsoptional | number | Exact number of decimals. |
minDecimalsoptional | number | Minimum decimals. |
maxDecimalsoptional | number | Maximum decimals. Defaults to 3. |
compactoptional | boolean | Short notation like 1.2K or 3.4M. |
styleoptional | "decimal" | "percent" | "percent" multiplies by 100 and adds %. |
unitoptional | string | Any Intl unit: "kilometer", "celsius", "megabyte"... |
unitDisplayoptional | "long" | "short" | "narrow" | How the unit is written. Defaults to "short". |
signDisplayoptional | "always" | "auto" | "never" | "exceptZero" | When to show the sign. "exceptZero" gives +5. |
groupingoptional | boolean | Thousands separators. Defaults to true. |
OrdinalOptions
Options for ordinal().
| Property | Type | Description |
|---|---|---|
localeoptional | string | Built in: en, fr, es, it, pt, de, nl. Defaults to the one set with setLocale(), or "en". |
suffixesoptional | Partial<Record<LDMLPluralRule, string>> | Your own suffixes, for other languages. |
ParseBytesOptions
Options for parseBytes().
| Property | Type | Description |
|---|---|---|
binaryoptional | boolean | 1 KB is 1024 bytes when true, 1000 when false. KiB units are always 1024. Defaults to true. |
VarianceOptions
Options for variance() and stdDev().
| Property | Type | Description |
|---|---|---|
sampleoptional | boolean | Sample statistic (divides by n - 1) instead of population. |