node-comfortv2.0.0

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);
GuideExplanations and examples for nc.num.
Read the guide →

Functions

nc.num.setLocale()

setLocale(locale: string): typeof nc.num

Sets the default language of format, currency, percent, abbreviate, ordinal and formatBytes.

Parameters

NameTypeDescription
localestringLike "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(): string

The current default language.

Returns string

Example

num.getLocale(); // "en"

nc.num.clamp()

clamp(value: number, min: number, max: number): number

Keeps a number between min and max.

Parameters

NameType
valuenumber
minnumber
maxnumber

Returns number

Example

num.clamp(150, 0, 100); // 100
num.clamp(-5, 0, 100);  // 0

nc.num.inRange()

inRange(value: number, min: number, max: number): boolean

Is the number between min and max, both included?

Parameters

NameType
valuenumber
minnumber
maxnumber

Returns boolean

Example

num.inRange(10, 0, 10); // true

nc.num.wrap()

wrap(value: number, min: number, max: number): number

Wraps a number around a range, like an angle or a carousel index. max is excluded.

Parameters

NameType
valuenumber
minnumber
maxnumber

Returns number

Example

num.wrap(370, 0, 360); // 10
num.wrap(-1, 0, 5);    // 4

nc.num.round()

round(value: number, decimals?: number): number

Rounds 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

NameTypeDescription
valuenumber
decimalsoptionalnumberNegative 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);     // -3

nc.num.floor()

floor(value: number, decimals?: number): number

Rounds down to decimals places.

Parameters

NameTypeDescription
valuenumber
decimalsoptionalnumberDefault: 0

Returns number

Example

num.floor(1.789, 2); // 1.78

nc.num.ceil()

ceil(value: number, decimals?: number): number

Rounds up to decimals places.

Parameters

NameTypeDescription
valuenumber
decimalsoptionalnumberDefault: 0

Returns number

Example

num.ceil(1.231, 2); // 1.24

nc.num.snap()

snap(value: number, step: number): number

Rounds to the nearest multiple of step.

Parameters

NameType
valuenumber
stepnumber

Returns number

Example

num.snap(17, 5);        // 15
num.snap(0.37, 0.25);   // 0.25

nc.num.approxEqual()

approxEqual(a: number, b: number, epsilon?: number): boolean

Are two numbers equal within a small tolerance? The right way to compare float results, since 0.1 + 0.2 === 0.3 is false.

Parameters

NameTypeDescription
anumber
bnumber
epsilonoptionalnumberAllowed difference, relative to the size of the numbers.Default: Number.EPSILON * 16

Returns boolean

Example

num.approxEqual(0.1 + 0.2, 0.3); // true

nc.num.lerp()

lerp(start: number, end: number, t: number): number

The value at ratio t between start and end.

Parameters

NameTypeDescription
startnumber
endnumber
tnumberUsually between 0 and 1.

Returns number

Example

num.lerp(0, 100, 0.25); // 25

nc.num.mapRange()

mapRange(value: number, inMin: number, inMax: number, outMin: number, outMax: number): number

Moves a number from one range to another, keeping its relative position.

Parameters

NameType
valuenumber
inMinnumber
inMaxnumber
outMinnumber
outMaxnumber

Returns number

Example

num.mapRange(5, 0, 10, 0, 100); // 50
num.mapRange(75, 0, 100, 1, 0); // 0.25

nc.num.random()

random(min?: number, max?: number): number

A random float from min (included) to max (excluded). Not for security: it uses Math.random.

Parameters

NameTypeDescription
minoptionalnumberDefault: 0
maxoptionalnumberDefault: 1

Returns number

Example

num.random(10, 20); // 13.84...

nc.num.randomInt()

randomInt(min: number, max: number): number

A random integer from min to max, both included. Not for security.

Parameters

NameType
minnumber
maxnumber

Returns number

Example

num.randomInt(1, 6); // a dice roll

nc.num.sum()

sum(values: Iterable<number>): number

Adds up numbers.

Parameters

NameType
valuesIterable<number>

Returns number

Example

num.sum([1, 2, 3]); // 6

nc.num.average()

average(values: Iterable<number>): number

The mean, or 0 for an empty list.

Parameters

NameType
valuesIterable<number>

Returns number

Example

num.average([2, 4, 9]); // 5

nc.num.median()

median(values: Iterable<number>): number

The middle value once sorted, or 0 for an empty list.

Parameters

NameType
valuesIterable<number>

Returns number

Example

num.median([3, 1, 2]);    // 2
num.median([1, 2, 3, 4]); // 2.5

nc.num.mode()

mode(values: Iterable<number>): number[]

The most frequent values.

Parameters

NameType
valuesIterable<number>

Returns number[]

Example

num.mode([1, 1, 2, 2, 3]); // [1, 2]

nc.num.variance()

variance(values: Iterable<number>, options?: VarianceOptions): number

The variance: the average squared distance from the mean.

Parameters

NameType
valuesIterable<number>
optionsoptionalVarianceOptions

Returns number

Example

num.variance([2, 4, 4, 4, 5, 5, 7, 9]); // 4

nc.num.stdDev()

stdDev(values: Iterable<number>, options?: VarianceOptions): number

The standard deviation.

Parameters

NameType
valuesIterable<number>
optionsoptionalVarianceOptions

Returns number

Example

num.stdDev([2, 4, 4, 4, 5, 5, 7, 9]); // 2

nc.num.percentile()

percentile(values: Iterable<number>, p: number): number

The value under which p percent of the values fall, interpolated like Excel's PERCENTILE.INC.

Parameters

NameTypeDescription
valuesIterable<number>
pnumberFrom 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 latency

nc.num.min()

min(values: Iterable<number>): number | undefined

The smallest number. Unlike Math.min(...array), huge arrays are fine.

Parameters

NameType
valuesIterable<number>

Returns number | undefined: undefined for an empty list.

nc.num.max()

max(values: Iterable<number>): number | undefined

The largest number. Unlike Math.max(...array), huge arrays are fine.

Parameters

NameType
valuesIterable<number>

Returns number | undefined: undefined for an empty list.

nc.num.percent()

percent(value: number, total: number, decimals?: number): number

What percentage value is of total. Returns 0 when total is 0.

Parameters

NameTypeDescription
valuenumber
totalnumber
decimalsoptionalnumberDefault: 2

Returns number

Example

num.percent(25, 200); // 12.5
num.percent(1, 3, 1); // 33.3

nc.num.gcd()

gcd(...values: number[]): number

Greatest common divisor.

Parameters

NameType
...values...number

Returns number

Example

num.gcd(12, 18, 27); // 3

nc.num.lcm()

lcm(...values: number[]): number

Least common multiple.

Parameters

NameType
...values...number

Returns number

Example

num.lcm(2, 3, 4); // 12

nc.num.isPrime()

isPrime(value: number): boolean

Is it a prime number?

Parameters

NameType
valuenumber

Returns boolean

Example

num.isPrime(7); // true
num.isPrime(1); // false

nc.num.factorial()

factorial(n: number, asBigInt?: boolean): number | bigint

n!. Pass true to get an exact bigint, since numbers lose precision past 18!.

Parameters

NameTypeDescription
nnumber
asBigIntoptionalbooleanDefault: false

Returns number | bigint

Throws RangeError If n is negative or not an integer.

Example

num.factorial(5);        // 120
num.factorial(25, true); // 15511210043330985984000000n

nc.num.isEven()

isEven(value: number): boolean

Is it even?

Parameters

NameType
valuenumber

Returns boolean

nc.num.isOdd()

isOdd(value: number): boolean

Is it odd? Negative numbers work too.

Parameters

NameType
valuenumber

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

NameTypeDescription
startnumber
endoptionalnumber
stepoptionalnumberDefaults 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): number

Reads a number from anything, ignoring trailing text like units.

Parameters

NameTypeDescription
valueunknown
fallbackoptionalnumberReturned 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);  // 0

nc.num.parseBytes()

parseBytes(value: string | number, options?: ParseBytesOptions): number

Turns a size like "10 MB" into bytes. The opposite of formatBytes().

Parameters

NameTypeDescription
valuestring | numberA size like "512kb" or "1.5G", or a number of bytes.
optionsoptionalParseBytesOptions

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 });  // 1000

nc.num.formatBytes()

formatBytes(bytes: number, options?: FormatBytesOptions): string

Formats a byte count as a readable size.

Parameters

NameType
bytesnumber
optionsoptionalFormatBytesOptions

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): string

Formats a number for display, with Intl.NumberFormat doing the work: separators, decimals, compact notation, percentages, units.

Parameters

NameType
valuenumber | bigint
optionsoptionalFormatNumberOptions

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): string

Formats an amount of money.

Parameters

NameTypeDescription
valuenumber | bigint
codestringA currency code like "EUR", "USD" or "JPY".
optionsoptionalCurrencyOptions

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): string

Shortens big numbers with K, M, B or T. For other languages, use format(value, { compact: true, locale }).

Parameters

NameTypeDescription
valuenumber
decimalsoptionalnumberDefault: 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): string

Adds thousands separators, leaving decimals alone.

Parameters

NameTypeDescription
valuenumber | string
separatoroptionalstringDefault: ","

Returns string

Example

num.thousands(1234567.89, " "); // "1 234 567.89"

nc.num.ordinal()

ordinal(value: number, options?: OrdinalOptions): string

Adds the ordinal suffix: 1st, 2nd, 3rd... in several languages.

Parameters

NameType
valuenumber
optionsoptionalOrdinalOptions

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().

PropertyTypeDescription
localeoptionalstringLanguage. Defaults to the one set with setLocale(), or "en".
decimalsoptionalnumberDefaults to the currency's usual decimals (2 for EUR, 0 for JPY).
displayoptional"symbol" | "code" | "name" | "narrowSymbol", , EUR or euros. Defaults to "symbol".
accountingoptionalbooleanShow negative amounts in parentheses, like ($5.00).

FormatBytesOptions

Options for formatBytes().

PropertyTypeDescription
decimalsoptionalnumberMaximum decimals. Defaults to 1.
binaryoptionalboolean1 KB is 1024 bytes when true, 1000 when false. Defaults to true.
iecoptionalbooleanUse KiB, MiB, GiB labels.
localeoptionalstringFormats the number for a language, like "fr" for "1,5 KB".
unitsoptionalstring[]Your own labels from bytes up, like ["o", "Ko", "Mo", "Go", "To"].

FormatNumberOptions

Options for format().

PropertyTypeDescription
localeoptionalstringLanguage, like "fr" or "en-US". Defaults to the one set with setLocale(), or "en".
decimalsoptionalnumberExact number of decimals.
minDecimalsoptionalnumberMinimum decimals.
maxDecimalsoptionalnumberMaximum decimals. Defaults to 3.
compactoptionalbooleanShort notation like 1.2K or 3.4M.
styleoptional"decimal" | "percent""percent" multiplies by 100 and adds %.
unitoptionalstringAny 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.
groupingoptionalbooleanThousands separators. Defaults to true.

OrdinalOptions

Options for ordinal().

PropertyTypeDescription
localeoptionalstringBuilt in: en, fr, es, it, pt, de, nl. Defaults to the one set with setLocale(), or "en".
suffixesoptionalPartial<Record<LDMLPluralRule, string>>Your own suffixes, for other languages.

ParseBytesOptions

Options for parseBytes().

PropertyTypeDescription
binaryoptionalboolean1 KB is 1024 bytes when true, 1000 when false. KiB units are always 1024. Defaults to true.

VarianceOptions

Options for variance() and stdDev().

PropertyTypeDescription
sampleoptionalbooleanSample statistic (divides by n - 1) instead of population.
node-comfort v2.0.0View the source