@helpers4/number 2.0.3 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -23,10 +23,8 @@ A set of helpers for working with URLs.
23
23
  - isOdd
24
24
  - isPositive
25
25
  - lerp
26
- - mean
27
26
  - random
28
27
  - roundTo
29
- - sum
30
28
  <!-- /AUTOMATIC-METHODS -->
31
29
 
32
30
  ## See
package/lib/index.d.ts CHANGED
@@ -30,9 +30,23 @@ declare function clamp(value: number, min: number, max: number): number;
30
30
  * digits and will silently truncate them. Increase `precision` if you
31
31
  * need to correct drift in very large numbers.
32
32
  *
33
+ * Note: IEEE-754 doubles carry at most ~17 significant decimal digits.
34
+ * Precision values above 17 pad with digits that reflect the underlying
35
+ * binary representation rather than correcting drift.
36
+ *
33
37
  * @param value - The floating-point value to correct
34
- * @param precision - Integer number of significant digits (default: 14)
38
+ * @param precision - Integer number of significant digits between 1 and 100
39
+ * (default: 14). Values above 17 are valid but expose binary noise beyond
40
+ * IEEE-754's meaningful range.
35
41
  * @returns The corrected value
42
+ * @example
43
+ * correctFloat(0.1 + 0.2) // => 0.3
44
+ * correctFloat(1.1 - 0.3) // => 0.8
45
+ * correctFloat(0.1 * 3) // => 0.3
46
+ *
47
+ * // Custom precision: keep 4 significant digits
48
+ * correctFloat(1.23456789, 4) // => 1.235
49
+ * correctFloat(1.23456789, 6) // => 1.23457
36
50
  * @since 2.0.2
37
51
  */
38
52
  declare function correctFloat(value: number, precision?: number): number;
@@ -80,15 +94,18 @@ interface ExtractNumberOptions {
80
94
  * @returns The extracted number, or `undefined` if none was found
81
95
  * @example
82
96
  * extractNumber('16.5px') // => 16.5
97
+ * extractNumber('.5rem') // => 0.5 (leading-dot decimal)
98
+ * extractNumber('-.5') // => -0.5 (leading-dot with sign)
83
99
  * extractNumber('Wafer 10') // => 10
84
100
  * extractNumber('xxx-111') // => 111 ('-' glued to text → separator)
85
101
  * extractNumber('xxx -111') // => -111 ('-' preceded by a space → sign)
102
+ * extractNumber('x-.5') // => 0.5 ('-' glued to 'x' → separator; leading-dot decimal follows)
86
103
  * extractNumber('-111') // => -111 ('-' at the start of the string → sign)
87
104
  * extractNumber('1e5 mol') // => 100000
88
105
  * extractNumber('1e5kg') // => 1 ('e5' glued to text → mantissa only)
89
106
  * extractNumber('no number') // => undefined
90
107
  * extractNumber(42) // => 42
91
- * @since 2.0.3
108
+ * @since 2.0.4
92
109
  */
93
110
  declare function extractNumber(value: unknown, options?: ExtractNumberOptions): number | undefined;
94
111
 
@@ -291,27 +308,6 @@ declare function isPositive(value: unknown): value is number;
291
308
  */
292
309
  declare function lerp(start: number, end: number, t: number): number;
293
310
 
294
- /**
295
- * This file is part of helpers4.
296
- * Copyright (C) 2025 baxyz
297
- * SPDX-License-Identifier: LGPL-3.0-or-later
298
- */
299
- /**
300
- * Calculates the arithmetic mean (average) of an array of numbers.
301
- * Returns `NaN` for an empty array.
302
- *
303
- * Pairs with {@link sum} for aggregate operations.
304
- *
305
- * @param array - The array of numbers to average
306
- * @returns The arithmetic mean, or `NaN` if the array is empty
307
- * @example
308
- * mean([1, 2, 3, 4]) // => 2.5
309
- * mean([10]) // => 10
310
- * mean([]) // => NaN
311
- * @since 2.0.0
312
- */
313
- declare function mean(array: readonly number[]): number;
314
-
315
311
  /**
316
312
  * This file is part of helpers4.
317
313
  * Copyright (C) 2025 baxyz
@@ -348,21 +344,5 @@ declare function randomIntBetween(min: number, max: number): number;
348
344
  */
349
345
  declare function roundTo(value: number, decimals: number): number;
350
346
 
351
- /**
352
- * This file is part of helpers4.
353
- * Copyright (C) 2025 baxyz
354
- * SPDX-License-Identifier: LGPL-3.0-or-later
355
- */
356
- /**
357
- * Calculates the sum of an array of numbers.
358
- * @param array - The array of numbers to sum
359
- * @returns The sum of all values
360
- * @example
361
- * sum([1, 2, 3, 4])
362
- * // => 10
363
- * @since 2.0.0
364
- */
365
- declare function sum(array: readonly number[]): number;
366
-
367
- export { clamp, correctFloat, extractNumber, formatCompact, formatSize, inRange, isEven, isNegative, isOdd, isPositive, lerp, mean, randomBetween, randomIntBetween, roundTo, sum };
347
+ export { clamp, correctFloat, extractNumber, formatCompact, formatSize, inRange, isEven, isNegative, isOdd, isPositive, lerp, randomBetween, randomIntBetween, roundTo };
368
348
  export type { ExtractNumberOptions, InRangeOptions };
package/lib/index.js CHANGED
@@ -34,22 +34,37 @@ function clamp(value, min, max) {
34
34
  * digits and will silently truncate them. Increase `precision` if you
35
35
  * need to correct drift in very large numbers.
36
36
  *
37
+ * Note: IEEE-754 doubles carry at most ~17 significant decimal digits.
38
+ * Precision values above 17 pad with digits that reflect the underlying
39
+ * binary representation rather than correcting drift.
40
+ *
37
41
  * @param value - The floating-point value to correct
38
- * @param precision - Integer number of significant digits (default: 14)
42
+ * @param precision - Integer number of significant digits between 1 and 100
43
+ * (default: 14). Values above 17 are valid but expose binary noise beyond
44
+ * IEEE-754's meaningful range.
39
45
  * @returns The corrected value
46
+ * @example
47
+ * correctFloat(0.1 + 0.2) // => 0.3
48
+ * correctFloat(1.1 - 0.3) // => 0.8
49
+ * correctFloat(0.1 * 3) // => 0.3
50
+ *
51
+ * // Custom precision: keep 4 significant digits
52
+ * correctFloat(1.23456789, 4) // => 1.235
53
+ * correctFloat(1.23456789, 6) // => 1.23457
40
54
  * @since 2.0.2
41
55
  */
42
56
  function correctFloat(value, precision = 14) {
43
57
  if (!Number.isFinite(value)) throw new RangeError(`correctFloat: value must be a finite number, got ${value}`);
44
58
  if (!Number.isInteger(precision) || precision < 1 || precision > 100) throw new RangeError(`correctFloat: precision must be an integer between 1 and 100, got ${precision}`);
45
59
  const result = parseFloat(value.toPrecision(precision));
46
- return Object.is(value, -0) && result === 0 ? -0 : result;
60
+ return Object.is(value, -0) ? -0 : result;
47
61
  }
48
62
  //#endregion
49
63
  //#region helpers/number/extractNumber.ts
50
- var NUMBER_TOKEN = /(-)?(\d+(?:\.\d+)?)([eE][+-]?\d+)?/g;
64
+ var NUMBER_TOKEN = /(-)?(\d+(?:\.\d+)?|(?<![\p{L}\p{N}_])\.\d+)([eE][+-]?\d+)?/u;
65
+ var WORD_CHAR = /[\p{L}\p{N}_]/u;
51
66
  function isWordChar(char) {
52
- return char !== void 0 && /[\p{L}\p{N}_]/u.test(char);
67
+ return char !== void 0 && WORD_CHAR.test(char);
53
68
  }
54
69
  /**
55
70
  * Extracts the first number embedded anywhere in a string, or passes through a `number`.
@@ -66,29 +81,32 @@ function isWordChar(char) {
66
81
  * @returns The extracted number, or `undefined` if none was found
67
82
  * @example
68
83
  * extractNumber('16.5px') // => 16.5
84
+ * extractNumber('.5rem') // => 0.5 (leading-dot decimal)
85
+ * extractNumber('-.5') // => -0.5 (leading-dot with sign)
69
86
  * extractNumber('Wafer 10') // => 10
70
87
  * extractNumber('xxx-111') // => 111 ('-' glued to text → separator)
71
88
  * extractNumber('xxx -111') // => -111 ('-' preceded by a space → sign)
89
+ * extractNumber('x-.5') // => 0.5 ('-' glued to 'x' → separator; leading-dot decimal follows)
72
90
  * extractNumber('-111') // => -111 ('-' at the start of the string → sign)
73
91
  * extractNumber('1e5 mol') // => 100000
74
92
  * extractNumber('1e5kg') // => 1 ('e5' glued to text → mantissa only)
75
93
  * extractNumber('no number') // => undefined
76
94
  * extractNumber(42) // => 42
77
- * @since 2.0.3
95
+ * @since 2.0.4
78
96
  */
79
97
  function extractNumber(value, options = {}) {
80
98
  const { sign = "auto", exponent = "auto" } = options;
81
99
  if (typeof value === "number") return Number.isNaN(value) ? void 0 : value;
82
100
  if (typeof value !== "string") return;
83
- NUMBER_TOKEN.lastIndex = 0;
101
+ const re = new RegExp(NUMBER_TOKEN.source, "gu");
84
102
  let match;
85
- while ((match = NUMBER_TOKEN.exec(value)) !== null) {
103
+ while ((match = re.exec(value)) !== null) {
86
104
  const [full, signChar, mantissa, exponentPart] = match;
87
105
  const start = match.index;
88
106
  if (signChar) {
89
107
  const before = value[start - 1];
90
108
  if (!(sign === "strict" ? true : sign === "ignore" ? false : !isWordChar(before))) {
91
- NUMBER_TOKEN.lastIndex = start + 1;
109
+ re.lastIndex = start + 1;
92
110
  continue;
93
111
  }
94
112
  }
@@ -321,31 +339,6 @@ function lerp(start, end, t) {
321
339
  return start + (end - start) * t;
322
340
  }
323
341
  //#endregion
324
- //#region helpers/number/mean.ts
325
- /**
326
- * This file is part of helpers4.
327
- * Copyright (C) 2025 baxyz
328
- * SPDX-License-Identifier: LGPL-3.0-or-later
329
- */
330
- /**
331
- * Calculates the arithmetic mean (average) of an array of numbers.
332
- * Returns `NaN` for an empty array.
333
- *
334
- * Pairs with {@link sum} for aggregate operations.
335
- *
336
- * @param array - The array of numbers to average
337
- * @returns The arithmetic mean, or `NaN` if the array is empty
338
- * @example
339
- * mean([1, 2, 3, 4]) // => 2.5
340
- * mean([10]) // => 10
341
- * mean([]) // => NaN
342
- * @since 2.0.0
343
- */
344
- function mean(array) {
345
- if (array.length === 0) return NaN;
346
- return array.reduce((acc, n) => acc + n, 0) / array.length;
347
- }
348
- //#endregion
349
342
  //#region helpers/number/random.ts
350
343
  /**
351
344
  * This file is part of helpers4.
@@ -391,25 +384,6 @@ function roundTo(value, decimals) {
391
384
  return Math.round(value * multiplier) / multiplier;
392
385
  }
393
386
  //#endregion
394
- //#region helpers/number/sum.ts
395
- /**
396
- * This file is part of helpers4.
397
- * Copyright (C) 2025 baxyz
398
- * SPDX-License-Identifier: LGPL-3.0-or-later
399
- */
400
- /**
401
- * Calculates the sum of an array of numbers.
402
- * @param array - The array of numbers to sum
403
- * @returns The sum of all values
404
- * @example
405
- * sum([1, 2, 3, 4])
406
- * // => 10
407
- * @since 2.0.0
408
- */
409
- function sum(array) {
410
- return array.reduce((acc, n) => acc + n, 0);
411
- }
412
- //#endregion
413
- export { clamp, correctFloat, extractNumber, formatCompact, formatSize, inRange, isEven, isNegative, isOdd, isPositive, lerp, mean, randomBetween, randomIntBetween, roundTo, sum };
387
+ export { clamp, correctFloat, extractNumber, formatCompact, formatSize, inRange, isEven, isNegative, isOdd, isPositive, lerp, randomBetween, randomIntBetween, roundTo };
414
388
 
415
389
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../helpers/number/clamp.ts","../../../helpers/number/correctFloat.ts","../../../helpers/number/extractNumber.ts","../../../helpers/number/formatCompact.ts","../../../helpers/number/formatSize.ts","../../../helpers/number/inRange.ts","../../../helpers/number/isEven.ts","../../../helpers/number/isNegative.ts","../../../helpers/number/isOdd.ts","../../../helpers/number/isPositive.ts","../../../helpers/number/lerp.ts","../../../helpers/number/mean.ts","../../../helpers/number/random.ts","../../../helpers/number/roundTo.ts","../../../helpers/number/sum.ts"],"sourcesContent":["/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Clamps a number between min and max values\n * @param value - The value to clamp\n * @param min - Minimum value\n * @param max - Maximum value\n * @returns Clamped value\n * @since 1.9.0\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Corrects floating-point arithmetic errors by rounding to a given number\n * of significant digits. Useful after calculations that accumulate binary\n * floating-point drift (e.g. `0.1 + 0.2 === 0.30000000000000004`).\n *\n * The default precision of 14 significant digits eliminates typical\n * rounding noise for values in the range used by most applications.\n * Note: for values whose integer part already consumes 14 or more digits\n * (i.e. |value| ≥ 1e13), toPrecision(14) has no room left for decimal\n * digits and will silently truncate them. Increase `precision` if you\n * need to correct drift in very large numbers.\n *\n * @param value - The floating-point value to correct\n * @param precision - Integer number of significant digits (default: 14)\n * @returns The corrected value\n * @since 2.0.2\n */\nexport function correctFloat(value: number, precision: number = 14): number {\n if (!Number.isFinite(value)) {\n throw new RangeError(`correctFloat: value must be a finite number, got ${value}`);\n }\n if (!Number.isInteger(precision) || precision < 1 || precision > 100) {\n throw new RangeError(`correctFloat: precision must be an integer between 1 and 100, got ${precision}`);\n }\n const result = parseFloat(value.toPrecision(precision));\n // toPrecision(-0) produces \"0.000…\" (no minus sign per spec) — restore the sign bit.\n return Object.is(value, -0) && result === 0 ? -0 : result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Options for {@link extractNumber}.\n */\nexport interface ExtractNumberOptions {\n /**\n * How to interpret a `-` immediately before the matched digits.\n * - `'auto'`: treated as a minus sign unless it is glued to a preceding letter/digit\n * (e.g. `'-111'` and `'xxx -111'` → negative, but `'xxx-111'` → separator, positive).\n * - `'strict'`: always treated as a minus sign.\n * - `'ignore'`: never treated as a minus sign (always a separator).\n * @default 'auto'\n */\n sign?: 'auto' | 'strict' | 'ignore';\n\n /**\n * How to interpret a trailing scientific-notation suffix (`e`/`E` + digits, e.g. `1.5e-10`).\n * - `'auto'`: treated as an exponent unless it is glued to a following letter/digit\n * (e.g. `'1e5'` and `'1e5 mol'` → exponential, but `'1e5kg'` → mantissa only).\n * - `'strict'`: always treated as an exponent.\n * - `'ignore'`: never treated as an exponent (mantissa only).\n * @default 'auto'\n */\n exponent?: 'auto' | 'strict' | 'ignore';\n}\n\nconst NUMBER_TOKEN = /(-)?(\\d+(?:\\.\\d+)?)([eE][+-]?\\d+)?/g;\n\nfunction isWordChar(char: string | undefined): boolean {\n return char !== undefined && /[\\p{L}\\p{N}_]/u.test(char);\n}\n\n/**\n * Extracts the first number embedded anywhere in a string, or passes through a `number`.\n *\n * Unlike a plain `parseFloat`/`parseInt`, the number does not need to be at the start of\n * the string: digits are searched for anywhere, so leading/trailing text (units, labels, ...)\n * is ignored. A `-` before the digits and a scientific-notation suffix (`e`/`E`) are\n * disambiguated with {@link ExtractNumberOptions.sign} and {@link ExtractNumberOptions.exponent}.\n *\n * Returns `undefined` if no number can be found.\n *\n * @param value - The value to extract a number from\n * @param options - Options controlling sign and exponent disambiguation\n * @returns The extracted number, or `undefined` if none was found\n * @example\n * extractNumber('16.5px') // => 16.5\n * extractNumber('Wafer 10') // => 10\n * extractNumber('xxx-111') // => 111 ('-' glued to text → separator)\n * extractNumber('xxx -111') // => -111 ('-' preceded by a space → sign)\n * extractNumber('-111') // => -111 ('-' at the start of the string → sign)\n * extractNumber('1e5 mol') // => 100000\n * extractNumber('1e5kg') // => 1 ('e5' glued to text → mantissa only)\n * extractNumber('no number') // => undefined\n * extractNumber(42) // => 42\n * @since 2.0.3\n */\nexport function extractNumber(value: unknown, options: ExtractNumberOptions = {}): number | undefined {\n const { sign = 'auto', exponent = 'auto' } = options;\n\n if (typeof value === 'number') {\n return Number.isNaN(value) ? undefined : value;\n }\n\n if (typeof value !== 'string') {\n return undefined;\n }\n\n NUMBER_TOKEN.lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = NUMBER_TOKEN.exec(value)) !== null) {\n const [full, signChar, mantissa, exponentPart] = match;\n const start = match.index;\n\n if (signChar) {\n const before = value[start - 1];\n const keepSign = sign === 'strict' ? true : sign === 'ignore' ? false : !isWordChar(before);\n\n if (!keepSign) {\n // Re-scan from right after the '-' so the digits are matched as a fresh, unsigned number.\n NUMBER_TOKEN.lastIndex = start + 1;\n continue;\n }\n }\n\n const keepExponent = exponentPart\n ? exponent === 'strict'\n ? true\n : exponent === 'ignore'\n ? false\n : !isWordChar(value[start + full.length])\n : false;\n\n const numericText = (signChar ?? '') + mantissa + (keepExponent ? exponentPart : '');\n return Number(numericText);\n }\n\n return undefined;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Formats a number using compact notation (e.g. `1_500_000 → \"1.5M\"`).\n *\n * Thin wrapper over `Intl.NumberFormat` with `notation: 'compact'`. Companion\n * of `formatSize` in the same `format*` family.\n *\n * @param value - The number to format.\n * @param locale - BCP 47 locale tag. Defaults to the runtime locale.\n * @returns A compact string representation of the number.\n * @example\n * formatCompact(1_500_000); // '1.5M' (en-US locale)\n * formatCompact(1_000); // '1K'\n * formatCompact(999); // '999'\n * formatCompact(1_500_000, 'fr'); // '1,5 M'\n * @since 2.0.0\n */\nexport function formatCompact(value: number, locale?: string): string {\n return new Intl.NumberFormat(locale, { notation: 'compact' }).format(value);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/** Size units in ascending order. */\nconst UNITS = ['B', 'KB', 'MB', 'GB', 'TB'] as const;\n\n/**\n * Format a byte count into a human-readable string with the appropriate unit.\n *\n * Each unit is 1024 of the previous (binary prefix). The result is formatted\n * with one decimal place.\n *\n * @param bytes - A non-negative integer representing a byte count.\n * @returns A human-readable string such as `'0.0B'`, `'1.5KB'`, `'3.2MB'`.\n * @example\n * formatSize(0) // '0.0B'\n * formatSize(512) // '512.0B'\n * formatSize(1024) // '1.0KB'\n * formatSize(1536) // '1.5KB'\n * formatSize(1_048_576) // '1.0MB'\n * formatSize(1_073_741_824) // '1.0GB'\n * @since 2.0.0\n */\nexport function formatSize(bytes: number): string {\n let size = bytes;\n let unitIndex = 0;\n\n while (size >= 1024 && unitIndex < UNITS.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n\n return `${size.toFixed(1)}${UNITS[unitIndex]}`;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Options for {@link inRange}.\n */\nexport interface InRangeOptions {\n /**\n * Which boundary (or boundaries) are included in the range.\n * - `'both'` (default): `min <= value <= max`\n * - `'min'`: `min <= value < max`\n * - `'max'`: `min < value <= max`\n * - `'none'`: `min < value < max`\n */\n inclusive?: 'both' | 'min' | 'max' | 'none';\n}\n\n/**\n * Checks whether a number falls within `[min, max]` (both inclusive by default).\n *\n * @param value - The number to test\n * @param min - Lower bound\n * @param max - Upper bound\n * @param options - Boundary inclusion mode (default: `'both'`)\n * @returns `true` if `value` is within the specified range\n * @example\n * inRange(5, 1, 10) // => true\n * inRange(1, 1, 10) // => true (min inclusive)\n * inRange(1, 1, 10, { inclusive: 'none' }) // => false\n * inRange(10, 1, 10, { inclusive: 'max' }) // => true\n * @since 2.0.0\n */\nexport function inRange(value: number, min: number, max: number, options: InRangeOptions = {}): boolean {\n const { inclusive = 'both' } = options;\n const minOk = inclusive === 'both' || inclusive === 'min' ? value >= min : value > min;\n const maxOk = inclusive === 'both' || inclusive === 'max' ? value <= max : value < max;\n return minOk && maxOk;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is an even integer.\n *\n * Returns `false` for non-numbers, non-integers, `NaN`, `Infinity`, and odd integers.\n *\n * @param value - The value to check\n * @returns `true` if value is an integer divisible by 2\n * @example\n * isEven(2) // => true\n * isEven(0) // => true\n * isEven(-4) // => true\n * isEven(3) // => false\n * isEven(1.5) // => false (not an integer)\n * isEven('2') // => false\n * @since 2.0.3\n */\nexport function isEven(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value % 2 === 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a number less than 0.\n *\n * Returns `false` for `NaN`, `0`, positive numbers, and non-number types.\n *\n * @param value - The value to check\n * @returns True if value is a negative number\n * @example\n * isNegative(-1) // => true\n * isNegative(-0.5) // => true\n * isNegative(-Infinity) // => true\n * isNegative(0) // => false\n * isNegative(1) // => false\n * isNegative(NaN) // => false\n * @since 2.0.0\n */\nexport function isNegative(value: unknown): value is number {\n return typeof value === 'number' && value < 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is an odd integer.\n *\n * Returns `false` for non-numbers, non-integers, `NaN`, `Infinity`, and even integers.\n *\n * @param value - The value to check\n * @returns `true` if value is an integer not divisible by 2\n * @example\n * isOdd(3) // => true\n * isOdd(1) // => true\n * isOdd(-7) // => true\n * isOdd(2) // => false\n * isOdd(1.5) // => false (not an integer)\n * isOdd('3') // => false\n * @since 2.0.3\n */\nexport function isOdd(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value % 2 !== 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a number greater than 0.\n *\n * Returns `false` for `NaN`, `0`, negative numbers, and non-number types.\n *\n * @param value - The value to check\n * @returns True if value is a positive number\n * @example\n * isPositive(42) // => true\n * isPositive(0.1) // => true\n * isPositive(Infinity) // => true\n * isPositive(0) // => false\n * isPositive(-1) // => false\n * isPositive(NaN) // => false\n * @since 2.0.0\n */\nexport function isPositive(value: unknown): value is number {\n return typeof value === 'number' && value > 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Linearly interpolates between `start` and `end` by the factor `t`.\n *\n * - `t = 0` returns `start`.\n * - `t = 1` returns `end`.\n * - Values of `t` outside `[0, 1]` extrapolate beyond the range.\n *\n * @param start - The start value.\n * @param end - The end value.\n * @param t - The interpolation factor.\n * @returns The interpolated value.\n * @example\n * lerp(0, 100, 0); // 0\n * lerp(0, 100, 1); // 100\n * lerp(0, 100, 0.5); // 50\n * lerp(0, 100, 0.25); // 25\n * @since 2.0.0\n */\nexport function lerp(start: number, end: number, t: number): number {\n if (t === 0) return start;\n if (t === 1) return end;\n if (Object.is(start, end)) return start;\n return start + (end - start) * t;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Calculates the arithmetic mean (average) of an array of numbers.\n * Returns `NaN` for an empty array.\n *\n * Pairs with {@link sum} for aggregate operations.\n *\n * @param array - The array of numbers to average\n * @returns The arithmetic mean, or `NaN` if the array is empty\n * @example\n * mean([1, 2, 3, 4]) // => 2.5\n * mean([10]) // => 10\n * mean([]) // => NaN\n * @since 2.0.0\n */\nexport function mean(array: readonly number[]): number {\n if (array.length === 0) return NaN;\n return array.reduce((acc, n) => acc + n, 0) / array.length;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Generates a random number between min and max (inclusive)\n * @param min - Minimum value\n * @param max - Maximum value\n * @returns Random number between min and max\n * @since 1.9.0\n */\nexport function randomBetween(min: number, max: number): number {\n return Math.random() * (max - min) + min;\n}\n\n/**\n * Generates a random integer between min and max (inclusive)\n * @param min - Minimum value\n * @param max - Maximum value\n * @returns Random integer between min and max\n * @since 1.9.0\n */\nexport function randomIntBetween(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Rounds a number to specified decimal places\n * @param value - The number to round\n * @param decimals - Number of decimal places\n * @returns Rounded number\n * @since 1.9.0\n */\nexport function roundTo(value: number, decimals: number): number {\n const multiplier = Math.pow(10, decimals);\n return Math.round(value * multiplier) / multiplier;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Calculates the sum of an array of numbers.\n * @param array - The array of numbers to sum\n * @returns The sum of all values\n * @example\n * sum([1, 2, 3, 4])\n * // => 10\n * @since 2.0.0\n */\nexport function sum(array: readonly number[]): number {\n return array.reduce((acc, n) => acc + n, 0);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../helpers/number/clamp.ts","../../../helpers/number/correctFloat.ts","../../../helpers/number/extractNumber.ts","../../../helpers/number/formatCompact.ts","../../../helpers/number/formatSize.ts","../../../helpers/number/inRange.ts","../../../helpers/number/isEven.ts","../../../helpers/number/isNegative.ts","../../../helpers/number/isOdd.ts","../../../helpers/number/isPositive.ts","../../../helpers/number/lerp.ts","../../../helpers/number/random.ts","../../../helpers/number/roundTo.ts"],"sourcesContent":["/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Clamps a number between min and max values\n * @param value - The value to clamp\n * @param min - Minimum value\n * @param max - Maximum value\n * @returns Clamped value\n * @since 1.9.0\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Corrects floating-point arithmetic errors by rounding to a given number\n * of significant digits. Useful after calculations that accumulate binary\n * floating-point drift (e.g. `0.1 + 0.2 === 0.30000000000000004`).\n *\n * The default precision of 14 significant digits eliminates typical\n * rounding noise for values in the range used by most applications.\n * Note: for values whose integer part already consumes 14 or more digits\n * (i.e. |value| ≥ 1e13), toPrecision(14) has no room left for decimal\n * digits and will silently truncate them. Increase `precision` if you\n * need to correct drift in very large numbers.\n *\n * Note: IEEE-754 doubles carry at most ~17 significant decimal digits.\n * Precision values above 17 pad with digits that reflect the underlying\n * binary representation rather than correcting drift.\n *\n * @param value - The floating-point value to correct\n * @param precision - Integer number of significant digits between 1 and 100\n * (default: 14). Values above 17 are valid but expose binary noise beyond\n * IEEE-754's meaningful range.\n * @returns The corrected value\n * @example\n * correctFloat(0.1 + 0.2) // => 0.3\n * correctFloat(1.1 - 0.3) // => 0.8\n * correctFloat(0.1 * 3) // => 0.3\n *\n * // Custom precision: keep 4 significant digits\n * correctFloat(1.23456789, 4) // => 1.235\n * correctFloat(1.23456789, 6) // => 1.23457\n * @since 2.0.2\n */\nexport function correctFloat(value: number, precision: number = 14): number {\n if (!Number.isFinite(value)) {\n throw new RangeError(`correctFloat: value must be a finite number, got ${value}`);\n }\n if (!Number.isInteger(precision) || precision < 1 || precision > 100) {\n throw new RangeError(`correctFloat: precision must be an integer between 1 and 100, got ${precision}`);\n }\n const result = parseFloat(value.toPrecision(precision));\n // toPrecision(-0) produces \"0.000…\" (no minus sign per spec) — restore the sign bit.\n return Object.is(value, -0) ? -0 : result;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Options for {@link extractNumber}.\n */\nexport interface ExtractNumberOptions {\n /**\n * How to interpret a `-` immediately before the matched digits.\n * - `'auto'`: treated as a minus sign unless it is glued to a preceding letter/digit\n * (e.g. `'-111'` and `'xxx -111'` → negative, but `'xxx-111'` → separator, positive).\n * - `'strict'`: always treated as a minus sign.\n * - `'ignore'`: never treated as a minus sign (always a separator).\n * @default 'auto'\n */\n sign?: 'auto' | 'strict' | 'ignore';\n\n /**\n * How to interpret a trailing scientific-notation suffix (`e`/`E` + digits, e.g. `1.5e-10`).\n * - `'auto'`: treated as an exponent unless it is glued to a following letter/digit\n * (e.g. `'1e5'` and `'1e5 mol'` → exponential, but `'1e5kg'` → mantissa only).\n * - `'strict'`: always treated as an exponent.\n * - `'ignore'`: never treated as an exponent (mantissa only).\n * @default 'auto'\n */\n exponent?: 'auto' | 'strict' | 'ignore';\n}\n\n// (?<![\\p{L}\\p{N}_]) prevents matching a leading-dot decimal immediately after a word\n// character (e.g. the '.5' in 'text.5' is a property separator, not a decimal point).\n// No `g` flag — cloned per call via `new RegExp(…, 'gu')` so each invocation has its own lastIndex.\nconst NUMBER_TOKEN = /(-)?(\\d+(?:\\.\\d+)?|(?<![\\p{L}\\p{N}_])\\.\\d+)([eE][+-]?\\d+)?/u;\nconst WORD_CHAR = /[\\p{L}\\p{N}_]/u;\n\nfunction isWordChar(char: string | undefined): boolean {\n return char !== undefined && WORD_CHAR.test(char);\n}\n\n/**\n * Extracts the first number embedded anywhere in a string, or passes through a `number`.\n *\n * Unlike a plain `parseFloat`/`parseInt`, the number does not need to be at the start of\n * the string: digits are searched for anywhere, so leading/trailing text (units, labels, ...)\n * is ignored. A `-` before the digits and a scientific-notation suffix (`e`/`E`) are\n * disambiguated with {@link ExtractNumberOptions.sign} and {@link ExtractNumberOptions.exponent}.\n *\n * Returns `undefined` if no number can be found.\n *\n * @param value - The value to extract a number from\n * @param options - Options controlling sign and exponent disambiguation\n * @returns The extracted number, or `undefined` if none was found\n * @example\n * extractNumber('16.5px') // => 16.5\n * extractNumber('.5rem') // => 0.5 (leading-dot decimal)\n * extractNumber('-.5') // => -0.5 (leading-dot with sign)\n * extractNumber('Wafer 10') // => 10\n * extractNumber('xxx-111') // => 111 ('-' glued to text → separator)\n * extractNumber('xxx -111') // => -111 ('-' preceded by a space → sign)\n * extractNumber('x-.5') // => 0.5 ('-' glued to 'x' → separator; leading-dot decimal follows)\n * extractNumber('-111') // => -111 ('-' at the start of the string → sign)\n * extractNumber('1e5 mol') // => 100000\n * extractNumber('1e5kg') // => 1 ('e5' glued to text → mantissa only)\n * extractNumber('no number') // => undefined\n * extractNumber(42) // => 42\n * @since 2.0.4\n */\nexport function extractNumber(value: unknown, options: ExtractNumberOptions = {}): number | undefined {\n const { sign = 'auto', exponent = 'auto' } = options;\n\n if (typeof value === 'number') {\n return Number.isNaN(value) ? undefined : value;\n }\n\n if (typeof value !== 'string') {\n return undefined;\n }\n\n const re = new RegExp(NUMBER_TOKEN.source, 'gu');\n let match: RegExpExecArray | null;\n\n while ((match = re.exec(value)) !== null) {\n const [full, signChar, mantissa, exponentPart] = match;\n const start = match.index;\n\n if (signChar) {\n const before = value[start - 1];\n const keepSign = sign === 'strict' ? true : sign === 'ignore' ? false : !isWordChar(before);\n\n if (!keepSign) {\n // Re-scan from right after the '-' so the digits are matched as a fresh, unsigned number.\n re.lastIndex = start + 1;\n continue;\n }\n }\n\n const keepExponent = exponentPart\n ? exponent === 'strict'\n ? true\n : exponent === 'ignore'\n ? false\n : !isWordChar(value[start + full.length])\n : false;\n\n const numericText = (signChar ?? '') + mantissa + (keepExponent ? exponentPart : '');\n return Number(numericText);\n }\n\n return undefined;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Formats a number using compact notation (e.g. `1_500_000 → \"1.5M\"`).\n *\n * Thin wrapper over `Intl.NumberFormat` with `notation: 'compact'`. Companion\n * of `formatSize` in the same `format*` family.\n *\n * @param value - The number to format.\n * @param locale - BCP 47 locale tag. Defaults to the runtime locale.\n * @returns A compact string representation of the number.\n * @example\n * formatCompact(1_500_000); // '1.5M' (en-US locale)\n * formatCompact(1_000); // '1K'\n * formatCompact(999); // '999'\n * formatCompact(1_500_000, 'fr'); // '1,5 M'\n * @since 2.0.0\n */\nexport function formatCompact(value: number, locale?: string): string {\n return new Intl.NumberFormat(locale, { notation: 'compact' }).format(value);\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/** Size units in ascending order. */\nconst UNITS = ['B', 'KB', 'MB', 'GB', 'TB'] as const;\n\n/**\n * Format a byte count into a human-readable string with the appropriate unit.\n *\n * Each unit is 1024 of the previous (binary prefix). The result is formatted\n * with one decimal place.\n *\n * @param bytes - A non-negative integer representing a byte count.\n * @returns A human-readable string such as `'0.0B'`, `'1.5KB'`, `'3.2MB'`.\n * @example\n * formatSize(0) // '0.0B'\n * formatSize(512) // '512.0B'\n * formatSize(1024) // '1.0KB'\n * formatSize(1536) // '1.5KB'\n * formatSize(1_048_576) // '1.0MB'\n * formatSize(1_073_741_824) // '1.0GB'\n * @since 2.0.0\n */\nexport function formatSize(bytes: number): string {\n let size = bytes;\n let unitIndex = 0;\n\n while (size >= 1024 && unitIndex < UNITS.length - 1) {\n size /= 1024;\n unitIndex++;\n }\n\n return `${size.toFixed(1)}${UNITS[unitIndex]}`;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Options for {@link inRange}.\n */\nexport interface InRangeOptions {\n /**\n * Which boundary (or boundaries) are included in the range.\n * - `'both'` (default): `min <= value <= max`\n * - `'min'`: `min <= value < max`\n * - `'max'`: `min < value <= max`\n * - `'none'`: `min < value < max`\n */\n inclusive?: 'both' | 'min' | 'max' | 'none';\n}\n\n/**\n * Checks whether a number falls within `[min, max]` (both inclusive by default).\n *\n * @param value - The number to test\n * @param min - Lower bound\n * @param max - Upper bound\n * @param options - Boundary inclusion mode (default: `'both'`)\n * @returns `true` if `value` is within the specified range\n * @example\n * inRange(5, 1, 10) // => true\n * inRange(1, 1, 10) // => true (min inclusive)\n * inRange(1, 1, 10, { inclusive: 'none' }) // => false\n * inRange(10, 1, 10, { inclusive: 'max' }) // => true\n * @since 2.0.0\n */\nexport function inRange(value: number, min: number, max: number, options: InRangeOptions = {}): boolean {\n const { inclusive = 'both' } = options;\n const minOk = inclusive === 'both' || inclusive === 'min' ? value >= min : value > min;\n const maxOk = inclusive === 'both' || inclusive === 'max' ? value <= max : value < max;\n return minOk && maxOk;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is an even integer.\n *\n * Returns `false` for non-numbers, non-integers, `NaN`, `Infinity`, and odd integers.\n *\n * @param value - The value to check\n * @returns `true` if value is an integer divisible by 2\n * @example\n * isEven(2) // => true\n * isEven(0) // => true\n * isEven(-4) // => true\n * isEven(3) // => false\n * isEven(1.5) // => false (not an integer)\n * isEven('2') // => false\n * @since 2.0.3\n */\nexport function isEven(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value % 2 === 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a number less than 0.\n *\n * Returns `false` for `NaN`, `0`, positive numbers, and non-number types.\n *\n * @param value - The value to check\n * @returns True if value is a negative number\n * @example\n * isNegative(-1) // => true\n * isNegative(-0.5) // => true\n * isNegative(-Infinity) // => true\n * isNegative(0) // => false\n * isNegative(1) // => false\n * isNegative(NaN) // => false\n * @since 2.0.0\n */\nexport function isNegative(value: unknown): value is number {\n return typeof value === 'number' && value < 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is an odd integer.\n *\n * Returns `false` for non-numbers, non-integers, `NaN`, `Infinity`, and even integers.\n *\n * @param value - The value to check\n * @returns `true` if value is an integer not divisible by 2\n * @example\n * isOdd(3) // => true\n * isOdd(1) // => true\n * isOdd(-7) // => true\n * isOdd(2) // => false\n * isOdd(1.5) // => false (not an integer)\n * isOdd('3') // => false\n * @since 2.0.3\n */\nexport function isOdd(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value % 2 !== 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Checks if a value is a number greater than 0.\n *\n * Returns `false` for `NaN`, `0`, negative numbers, and non-number types.\n *\n * @param value - The value to check\n * @returns True if value is a positive number\n * @example\n * isPositive(42) // => true\n * isPositive(0.1) // => true\n * isPositive(Infinity) // => true\n * isPositive(0) // => false\n * isPositive(-1) // => false\n * isPositive(NaN) // => false\n * @since 2.0.0\n */\nexport function isPositive(value: unknown): value is number {\n return typeof value === 'number' && value > 0;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Linearly interpolates between `start` and `end` by the factor `t`.\n *\n * - `t = 0` returns `start`.\n * - `t = 1` returns `end`.\n * - Values of `t` outside `[0, 1]` extrapolate beyond the range.\n *\n * @param start - The start value.\n * @param end - The end value.\n * @param t - The interpolation factor.\n * @returns The interpolated value.\n * @example\n * lerp(0, 100, 0); // 0\n * lerp(0, 100, 1); // 100\n * lerp(0, 100, 0.5); // 50\n * lerp(0, 100, 0.25); // 25\n * @since 2.0.0\n */\nexport function lerp(start: number, end: number, t: number): number {\n if (t === 0) return start;\n if (t === 1) return end;\n if (Object.is(start, end)) return start;\n return start + (end - start) * t;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Generates a random number between min and max (inclusive)\n * @param min - Minimum value\n * @param max - Maximum value\n * @returns Random number between min and max\n * @since 1.9.0\n */\nexport function randomBetween(min: number, max: number): number {\n return Math.random() * (max - min) + min;\n}\n\n/**\n * Generates a random integer between min and max (inclusive)\n * @param min - Minimum value\n * @param max - Maximum value\n * @returns Random integer between min and max\n * @since 1.9.0\n */\nexport function randomIntBetween(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/**\n * Rounds a number to specified decimal places\n * @param value - The number to round\n * @param decimals - Number of decimal places\n * @returns Rounded number\n * @since 1.9.0\n */\nexport function roundTo(value: number, decimals: number): number {\n const multiplier = Math.pow(10, decimals);\n return Math.round(value * multiplier) / multiplier;\n}\n"],"mappings":";;;;;;;;;;;;;;AAcA,SAAgB,MAAM,OAAe,KAAa,KAAqB;CACrE,OAAO,KAAK,IAAI,KAAK,IAAI,OAAO,GAAG,GAAG,GAAG;AAC3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACqBA,SAAgB,aAAa,OAAe,YAAoB,IAAY;CAC1E,IAAI,CAAC,OAAO,SAAS,KAAK,GACxB,MAAM,IAAI,WAAW,oDAAoD,OAAO;CAElF,IAAI,CAAC,OAAO,UAAU,SAAS,KAAK,YAAY,KAAK,YAAY,KAC/D,MAAM,IAAI,WAAW,qEAAqE,WAAW;CAEvG,MAAM,SAAS,WAAW,MAAM,YAAY,SAAS,CAAC;CAEtD,OAAO,OAAO,GAAG,OAAO,EAAE,IAAI,KAAK;AACrC;;;ACbA,IAAM,eAAe;AACrB,IAAM,YAAY;AAElB,SAAS,WAAW,MAAmC;CACrD,OAAO,SAAS,KAAA,KAAa,UAAU,KAAK,IAAI;AAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAgB,cAAc,OAAgB,UAAgC,CAAC,GAAuB;CACpG,MAAM,EAAE,OAAO,QAAQ,WAAW,WAAW;CAE7C,IAAI,OAAO,UAAU,UACnB,OAAO,OAAO,MAAM,KAAK,IAAI,KAAA,IAAY;CAG3C,IAAI,OAAO,UAAU,UACnB;CAGF,MAAM,KAAK,IAAI,OAAO,aAAa,QAAQ,IAAI;CAC/C,IAAI;CAEJ,QAAQ,QAAQ,GAAG,KAAK,KAAK,OAAO,MAAM;EACxC,MAAM,CAAC,MAAM,UAAU,UAAU,gBAAgB;EACjD,MAAM,QAAQ,MAAM;EAEpB,IAAI,UAAU;GACZ,MAAM,SAAS,MAAM,QAAQ;GAG7B,IAAI,EAFa,SAAS,WAAW,OAAO,SAAS,WAAW,QAAQ,CAAC,WAAW,MAAM,IAE3E;IAEb,GAAG,YAAY,QAAQ;IACvB;GACF;EACF;EAEA,MAAM,eAAe,eACjB,aAAa,WACX,OACA,aAAa,WACX,QACA,CAAC,WAAW,MAAM,QAAQ,KAAK,OAAO,IAC1C;EAEJ,MAAM,eAAe,YAAY,MAAM,YAAY,eAAe,eAAe;EACjF,OAAO,OAAO,WAAW;CAC3B;AAGF;;;;;;;;;;;;;;;;;;;;;;;;ACzFA,SAAgB,cAAc,OAAe,QAAyB;CACpE,OAAO,IAAI,KAAK,aAAa,QAAQ,EAAE,UAAU,UAAU,CAAC,EAAE,OAAO,KAAK;AAC5E;;;;;;;;;ACjBA,IAAM,QAAQ;CAAC;CAAK;CAAM;CAAM;CAAM;AAAI;;;;;;;;;;;;;;;;;;AAmB1C,SAAgB,WAAW,OAAuB;CAChD,IAAI,OAAO;CACX,IAAI,YAAY;CAEhB,OAAO,QAAQ,QAAQ,YAAY,MAAM,SAAS,GAAG;EACnD,QAAQ;EACR;CACF;CAEA,OAAO,GAAG,KAAK,QAAQ,CAAC,IAAI,MAAM;AACpC;;;;;;;;;;;;;;;;;;ACDA,SAAgB,QAAQ,OAAe,KAAa,KAAa,UAA0B,CAAC,GAAY;CACtG,MAAM,EAAE,YAAY,WAAW;CAG/B,QAFc,cAAc,UAAU,cAAc,QAAQ,SAAS,MAAM,QAAQ,SACrE,cAAc,UAAU,cAAc,QAAQ,SAAS,MAAM,QAAQ;AAErF;;;;;;;;;;;;;;;;;;;;;;;;AClBA,SAAgB,OAAO,OAAiC;CACtD,OAAO,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,KAAK,QAAQ,MAAM;AAC/E;;;;;;;;;;;;;;;;;;;;;;;;ACFA,SAAgB,WAAW,OAAiC;CAC1D,OAAO,OAAO,UAAU,YAAY,QAAQ;AAC9C;;;;;;;;;;;;;;;;;;;;;;;;ACFA,SAAgB,MAAM,OAAiC;CACrD,OAAO,OAAO,UAAU,YAAY,OAAO,UAAU,KAAK,KAAK,QAAQ,MAAM;AAC/E;;;;;;;;;;;;;;;;;;;;;;;;ACFA,SAAgB,WAAW,OAAiC;CAC1D,OAAO,OAAO,UAAU,YAAY,QAAQ;AAC9C;;;;;;;;;;;;;;;;;;;;;;;;;;ACAA,SAAgB,KAAK,OAAe,KAAa,GAAmB;CAClE,IAAI,MAAM,GAAG,OAAO;CACpB,IAAI,MAAM,GAAG,OAAO;CACpB,IAAI,OAAO,GAAG,OAAO,GAAG,GAAG,OAAO;CAClC,OAAO,SAAS,MAAM,SAAS;AACjC;;;;;;;;;;;;;;;AChBA,SAAgB,cAAc,KAAa,KAAqB;CAC9D,OAAO,KAAK,OAAO,KAAK,MAAM,OAAO;AACvC;;;;;;;;AASA,SAAgB,iBAAiB,KAAa,KAAqB;CACjE,OAAO,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,MAAM,EAAE,IAAI;AACvD;;;;;;;;;;;;;;;ACbA,SAAgB,QAAQ,OAAe,UAA0B;CAC/D,MAAM,aAAa,KAAK,IAAI,IAAI,QAAQ;CACxC,OAAO,KAAK,MAAM,QAAQ,UAAU,IAAI;AAC1C"}
package/llms.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  # @helpers4/number
2
2
 
3
3
  > Tree-shakable TypeScript utility functions for the `number` domain.
4
- > Package: `@helpers4/number` — Version: 2.0.3
4
+ > Package: `@helpers4/number` — Version: 2.1.0
5
5
  > License: LGPL-3.0-or-later
6
6
 
7
7
  ## Installation
@@ -33,11 +33,9 @@ import { clamp, correctFloat, extractNumber, ... } from '@helpers4/number';
33
33
  | `isOdd` | Checks if a value is an odd integer. Returns `false` for non-numbers, non-integers, `NaN`, `Infinit |
34
34
  | `isPositive` | Checks if a value is a number greater than 0. Returns `false` for `NaN`, `0`, negative numbers, and |
35
35
  | `lerp` | Linearly interpolates between `start` and `end` by the factor `t`. - `t = 0` returns `start`. - `t |
36
- | `mean` | Calculates the arithmetic mean (average) of an array of numbers. Returns `NaN` for an empty array. |
37
36
  | `randomBetween` | Generates a random number between min and max (inclusive) |
38
37
  | `randomIntBetween` | Generates a random integer between min and max (inclusive) |
39
38
  | `roundTo` | Rounds a number to specified decimal places |
40
- | `sum` | Calculates the sum of an array of numbers. |
41
39
 
42
40
  ---
43
41
 
@@ -88,6 +86,10 @@ Note: for values whose integer part already consumes 14 or more digits
88
86
  digits and will silently truncate them. Increase `precision` if you
89
87
  need to correct drift in very large numbers.
90
88
 
89
+ Note: IEEE-754 doubles carry at most ~17 significant decimal digits.
90
+ Precision values above 17 pad with digits that reflect the underlying
91
+ binary representation rather than correcting drift.
92
+
91
93
  ```typescript
92
94
  import { correctFloat } from '@helpers4/number';
93
95
 
@@ -97,7 +99,9 @@ correctFloat(value: number, precision: number): number
97
99
  **Parameters:**
98
100
 
99
101
  - `value: number` — The floating-point value to correct
100
- - `precision: number` (default: `14`) — Integer number of significant digits (default: 14)
102
+ - `precision: number` (default: `14`) — Integer number of significant digits between 1 and 100
103
+ (default: 14). Values above 17 are valid but expose binary noise beyond
104
+ IEEE-754's meaningful range.
101
105
 
102
106
  **Returns:** `number` — The corrected value
103
107
 
@@ -154,9 +158,12 @@ extractNumber(value: unknown, options: ExtractNumberOptions): number | undefined
154
158
  ```typescript
155
159
  ```ts
156
160
  extractNumber('16.5px') // => 16.5
161
+ extractNumber('.5rem') // => 0.5 (leading-dot decimal)
162
+ extractNumber('-.5') // => -0.5 (leading-dot with sign)
157
163
  extractNumber('Wafer 10') // => 10
158
164
  extractNumber('xxx-111') // => 111 ('-' glued to text → separator)
159
165
  extractNumber('xxx -111') // => -111 ('-' preceded by a space → sign)
166
+ extractNumber('x-.5') // => 0.5 ('-' glued to 'x' → separator; leading-dot decimal follows)
160
167
  extractNumber('-111') // => -111 ('-' at the start of the string → sign)
161
168
  extractNumber('1e5 mol') // => 100000
162
169
  extractNumber('1e5kg') // => 1 ('e5' glued to text → mantissa only)
@@ -490,39 +497,6 @@ lerp(0, 10, 2) // => 20 (extrapolation)
490
497
 
491
498
  ---
492
499
 
493
- ### `mean`
494
-
495
- Calculates the arithmetic mean (average) of an array of numbers.
496
- Returns `NaN` for an empty array.
497
-
498
- Pairs with sum for aggregate operations.
499
-
500
- ```typescript
501
- import { mean } from '@helpers4/number';
502
-
503
- mean(array: readonly number[]): number
504
- ```
505
-
506
- **Parameters:**
507
-
508
- - `array: readonly number[]` — The array of numbers to average
509
-
510
- **Returns:** `number` — The arithmetic mean, or `NaN` if the array is empty
511
-
512
- **Examples:**
513
-
514
- *Average a list of numbers*
515
-
516
- Returns the arithmetic mean of the array; NaN for empty arrays.
517
-
518
- ```typescript
519
- mean([1, 2, 3, 4]) // => 2.5
520
- mean([10, 20, 30]) // => 20
521
- mean([]) // => NaN
522
- ```
523
-
524
- ---
525
-
526
500
  ### `randomBetween`
527
501
 
528
502
  Generates a random number between min and max (inclusive)
@@ -619,41 +593,3 @@ roundTo(3.7, 0)
619
593
  ```
620
594
 
621
595
  ---
622
-
623
- ### `sum`
624
-
625
- Calculates the sum of an array of numbers.
626
-
627
- ```typescript
628
- import { sum } from '@helpers4/number';
629
-
630
- sum(array: readonly number[]): number
631
- ```
632
-
633
- **Parameters:**
634
-
635
- - `array: readonly number[]` — The array of numbers to sum
636
-
637
- **Returns:** `number` — The sum of all values
638
-
639
- **Examples:**
640
-
641
- *Sum numbers*
642
-
643
- Calculates the sum of an array of numbers.
644
-
645
- ```typescript
646
- sum([1, 2, 3, 4])
647
- // => 10
648
- ```
649
-
650
- *Sum with negative numbers*
651
-
652
- Handles negative numbers correctly.
653
-
654
- ```typescript
655
- sum([10, -3, 5, -2])
656
- // => 10
657
- ```
658
-
659
- ---
package/meta/api.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "category": "number",
3
- "version": "2.0.3",
3
+ "version": "2.1.0",
4
4
  "functions": [
5
5
  {
6
6
  "name": "clamp",
@@ -46,12 +46,12 @@
46
46
  {
47
47
  "name": "correctFloat",
48
48
  "kind": "function",
49
- "description": "Corrects floating-point arithmetic errors by rounding to a given number\nof significant digits. Useful after calculations that accumulate binary\nfloating-point drift (e.g. `0.1 + 0.2 === 0.30000000000000004`).\n\nThe default precision of 14 significant digits eliminates typical\nrounding noise for values in the range used by most applications.\nNote: for values whose integer part already consumes 14 or more digits\n(i.e. |value| ≥ 1e13), toPrecision(14) has no room left for decimal\ndigits and will silently truncate them. Increase `precision` if you\nneed to correct drift in very large numbers.",
49
+ "description": "Corrects floating-point arithmetic errors by rounding to a given number\nof significant digits. Useful after calculations that accumulate binary\nfloating-point drift (e.g. `0.1 + 0.2 === 0.30000000000000004`).\n\nThe default precision of 14 significant digits eliminates typical\nrounding noise for values in the range used by most applications.\nNote: for values whose integer part already consumes 14 or more digits\n(i.e. |value| ≥ 1e13), toPrecision(14) has no room left for decimal\ndigits and will silently truncate them. Increase `precision` if you\nneed to correct drift in very large numbers.\n\nNote: IEEE-754 doubles carry at most ~17 significant decimal digits.\nPrecision values above 17 pad with digits that reflect the underlying\nbinary representation rather than correcting drift.",
50
50
  "since": "2.0.2",
51
51
  "signatures": [
52
52
  {
53
53
  "signature": "correctFloat(value: number, precision: number): number",
54
- "description": "Corrects floating-point arithmetic errors by rounding to a given number\nof significant digits. Useful after calculations that accumulate binary\nfloating-point drift (e.g. `0.1 + 0.2 === 0.30000000000000004`).\n\nThe default precision of 14 significant digits eliminates typical\nrounding noise for values in the range used by most applications.\nNote: for values whose integer part already consumes 14 or more digits\n(i.e. |value| ≥ 1e13), toPrecision(14) has no room left for decimal\ndigits and will silently truncate them. Increase `precision` if you\nneed to correct drift in very large numbers.",
54
+ "description": "Corrects floating-point arithmetic errors by rounding to a given number\nof significant digits. Useful after calculations that accumulate binary\nfloating-point drift (e.g. `0.1 + 0.2 === 0.30000000000000004`).\n\nThe default precision of 14 significant digits eliminates typical\nrounding noise for values in the range used by most applications.\nNote: for values whose integer part already consumes 14 or more digits\n(i.e. |value| ≥ 1e13), toPrecision(14) has no room left for decimal\ndigits and will silently truncate them. Increase `precision` if you\nneed to correct drift in very large numbers.\n\nNote: IEEE-754 doubles carry at most ~17 significant decimal digits.\nPrecision values above 17 pad with digits that reflect the underlying\nbinary representation rather than correcting drift.",
55
55
  "params": [
56
56
  {
57
57
  "name": "value",
@@ -61,7 +61,7 @@
61
61
  {
62
62
  "name": "precision",
63
63
  "type": "number",
64
- "description": "Integer number of significant digits (default: 14)",
64
+ "description": "Integer number of significant digits between 1 and 100\n (default: 14). Values above 17 are valid but expose binary noise beyond\n IEEE-754's meaningful range.",
65
65
  "defaultValue": "14"
66
66
  }
67
67
  ],
@@ -89,7 +89,7 @@
89
89
  "name": "extractNumber",
90
90
  "kind": "function",
91
91
  "description": "Extracts the first number embedded anywhere in a string, or passes through a `number`.\n\nUnlike a plain `parseFloat`/`parseInt`, the number does not need to be at the start of\nthe string: digits are searched for anywhere, so leading/trailing text (units, labels, ...)\nis ignored. A `-` before the digits and a scientific-notation suffix (`e`/`E`) are\ndisambiguated with ExtractNumberOptions.sign and ExtractNumberOptions.exponent.\n\nReturns `undefined` if no number can be found.",
92
- "since": "2.0.3",
92
+ "since": "2.0.4",
93
93
  "signatures": [
94
94
  {
95
95
  "signature": "extractNumber(value: unknown, options: ExtractNumberOptions): number | undefined",
@@ -117,7 +117,7 @@
117
117
  {
118
118
  "title": "extractNumber",
119
119
  "description": "",
120
- "code": "```ts\nextractNumber('16.5px') // => 16.5\nextractNumber('Wafer 10') // => 10\nextractNumber('xxx-111') // => 111 ('-' glued to text → separator)\nextractNumber('xxx -111') // => -111 ('-' preceded by a space → sign)\nextractNumber('-111') // => -111 ('-' at the start of the string → sign)\nextractNumber('1e5 mol') // => 100000\nextractNumber('1e5kg') // => 1 ('e5' glued to text → mantissa only)\nextractNumber('no number') // => undefined\nextractNumber(42) // => 42\n```"
120
+ "code": "```ts\nextractNumber('16.5px') // => 16.5\nextractNumber('.5rem') // => 0.5 (leading-dot decimal)\nextractNumber('-.5') // => -0.5 (leading-dot with sign)\nextractNumber('Wafer 10') // => 10\nextractNumber('xxx-111') // => 111 ('-' glued to text → separator)\nextractNumber('xxx -111') // => -111 ('-' preceded by a space → sign)\nextractNumber('x-.5') // => 0.5 ('-' glued to 'x' → separator; leading-dot decimal follows)\nextractNumber('-111') // => -111 ('-' at the start of the string → sign)\nextractNumber('1e5 mol') // => 100000\nextractNumber('1e5kg') // => 1 ('e5' glued to text → mantissa only)\nextractNumber('no number') // => undefined\nextractNumber(42) // => 42\n```"
121
121
  }
122
122
  ],
123
123
  "sourceFile": "extractNumber.ts"
@@ -427,37 +427,6 @@
427
427
  ],
428
428
  "sourceFile": "lerp.ts"
429
429
  },
430
- {
431
- "name": "mean",
432
- "kind": "function",
433
- "description": "Calculates the arithmetic mean (average) of an array of numbers.\nReturns `NaN` for an empty array.\n\nPairs with sum for aggregate operations.",
434
- "since": "2.0.0",
435
- "signatures": [
436
- {
437
- "signature": "mean(array: readonly number[]): number",
438
- "description": "Calculates the arithmetic mean (average) of an array of numbers.\nReturns `NaN` for an empty array.\n\nPairs with sum for aggregate operations.",
439
- "params": [
440
- {
441
- "name": "array",
442
- "type": "readonly number[]",
443
- "description": "The array of numbers to average"
444
- }
445
- ],
446
- "returns": {
447
- "type": "number",
448
- "description": "The arithmetic mean, or `NaN` if the array is empty"
449
- }
450
- }
451
- ],
452
- "examples": [
453
- {
454
- "title": "Average a list of numbers",
455
- "description": "Returns the arithmetic mean of the array; NaN for empty arrays.",
456
- "code": "mean([1, 2, 3, 4]) // => 2.5\nmean([10, 20, 30]) // => 20\nmean([]) // => NaN"
457
- }
458
- ],
459
- "sourceFile": "mean.ts"
460
- },
461
430
  {
462
431
  "name": "randomBetween",
463
432
  "kind": "function",
@@ -569,42 +538,6 @@
569
538
  }
570
539
  ],
571
540
  "sourceFile": "roundTo.ts"
572
- },
573
- {
574
- "name": "sum",
575
- "kind": "function",
576
- "description": "Calculates the sum of an array of numbers.",
577
- "since": "2.0.0",
578
- "signatures": [
579
- {
580
- "signature": "sum(array: readonly number[]): number",
581
- "description": "Calculates the sum of an array of numbers.",
582
- "params": [
583
- {
584
- "name": "array",
585
- "type": "readonly number[]",
586
- "description": "The array of numbers to sum"
587
- }
588
- ],
589
- "returns": {
590
- "type": "number",
591
- "description": "The sum of all values"
592
- }
593
- }
594
- ],
595
- "examples": [
596
- {
597
- "title": "Sum numbers",
598
- "description": "Calculates the sum of an array of numbers.",
599
- "code": "sum([1, 2, 3, 4])\n// => 10"
600
- },
601
- {
602
- "title": "Sum with negative numbers",
603
- "description": "Handles negative numbers correctly.",
604
- "code": "sum([10, -3, 5, -2])\n// => 10"
605
- }
606
- ],
607
- "sourceFile": "sum.ts"
608
541
  }
609
542
  ]
610
543
  }
@@ -32,7 +32,7 @@
32
32
  {
33
33
  "title": "extractNumber",
34
34
  "description": "",
35
- "code": "```ts\nextractNumber('16.5px') // => 16.5\nextractNumber('Wafer 10') // => 10\nextractNumber('xxx-111') // => 111 ('-' glued to text → separator)\nextractNumber('xxx -111') // => -111 ('-' preceded by a space → sign)\nextractNumber('-111') // => -111 ('-' at the start of the string → sign)\nextractNumber('1e5 mol') // => 100000\nextractNumber('1e5kg') // => 1 ('e5' glued to text → mantissa only)\nextractNumber('no number') // => undefined\nextractNumber(42) // => 42\n```"
35
+ "code": "```ts\nextractNumber('16.5px') // => 16.5\nextractNumber('.5rem') // => 0.5 (leading-dot decimal)\nextractNumber('-.5') // => -0.5 (leading-dot with sign)\nextractNumber('Wafer 10') // => 10\nextractNumber('xxx-111') // => 111 ('-' glued to text → separator)\nextractNumber('xxx -111') // => -111 ('-' preceded by a space → sign)\nextractNumber('x-.5') // => 0.5 ('-' glued to 'x' → separator; leading-dot decimal follows)\nextractNumber('-111') // => -111 ('-' at the start of the string → sign)\nextractNumber('1e5 mol') // => 100000\nextractNumber('1e5kg') // => 1 ('e5' glued to text → mantissa only)\nextractNumber('no number') // => undefined\nextractNumber(42) // => 42\n```"
36
36
  }
37
37
  ]
38
38
  },
@@ -141,16 +141,6 @@
141
141
  }
142
142
  ]
143
143
  },
144
- {
145
- "name": "mean",
146
- "examples": [
147
- {
148
- "title": "Average a list of numbers",
149
- "description": "Returns the arithmetic mean of the array; NaN for empty arrays.",
150
- "code": "mean([1, 2, 3, 4]) // => 2.5\nmean([10, 20, 30]) // => 20\nmean([]) // => NaN"
151
- }
152
- ]
153
- },
154
144
  {
155
145
  "name": "randomBetween",
156
146
  "examples": [
@@ -180,21 +170,6 @@
180
170
  "code": "roundTo(3.7, 0)\n// => 4"
181
171
  }
182
172
  ]
183
- },
184
- {
185
- "name": "sum",
186
- "examples": [
187
- {
188
- "title": "Sum numbers",
189
- "description": "Calculates the sum of an array of numbers.",
190
- "code": "sum([1, 2, 3, 4])\n// => 10"
191
- },
192
- {
193
- "title": "Sum with negative numbers",
194
- "description": "Handles negative numbers correctly.",
195
- "code": "sum([10, -3, 5, -2])\n// => 10"
196
- }
197
- ]
198
173
  }
199
174
  ]
200
175
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helpers4/number",
3
- "version": "2.0.3",
3
+ "version": "2.1.0",
4
4
  "description": "A set of helpers in TS/JS, compatible with tree-shaking, for number.",
5
5
  "author": "baxyz <baxy@etik.com>",
6
6
  "license": "LGPL-3.0",
@@ -38,10 +38,8 @@
38
38
  "isOdd",
39
39
  "isPositive",
40
40
  "lerp",
41
- "mean",
42
41
  "random",
43
- "roundTo",
44
- "sum"
42
+ "roundTo"
45
43
  ],
46
44
  "files": [
47
45
  "lib/index.js",