smart-unit 1.0.4 → 2.0.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 +48 -151
- package/README.zh-CN.md +37 -140
- package/dist/SmartUnit.d.ts +60 -0
- package/dist/SmartUnitBase.d.ts +77 -0
- package/dist/SmartUnitPrecision.d.ts +82 -0
- package/dist/index.cjs +166 -0
- package/dist/index.d.ts +3 -104
- package/dist/index.mjs +160 -0
- package/dist/precision.cjs +195 -0
- package/dist/precision.d.ts +9 -0
- package/dist/precision.mjs +189 -0
- package/dist/utils-C1byK7Uk.js +146 -0
- package/dist/utils-DqEXot5a.js +149 -0
- package/dist/utils.d.ts +32 -0
- package/package.json +36 -30
- package/dist/browser.umd.js +0 -14
- package/dist/index.esm.js +0 -228
- package/dist/index.js +0 -235
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { type Decimal } from 'decimal.js';
|
|
2
|
+
import { SmartUnitBase } from './SmartUnitBase';
|
|
3
|
+
import { type FormattedValue, type FractionDigits, type InputNumber, type SmartUnitOptions } from './utils';
|
|
4
|
+
export type DecimalOptions = Decimal.Config;
|
|
5
|
+
export type NumPrecision = InputNumber | string | bigint | Decimal;
|
|
6
|
+
export interface FormattedValuePrecision<U extends string> extends FormattedValue<U> {
|
|
7
|
+
decimal: Decimal;
|
|
8
|
+
}
|
|
9
|
+
export interface SmartUnitPrecisionOptions extends SmartUnitOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Decimal.js configuration options
|
|
12
|
+
* - Creates an isolated Decimal class for this SmartUnit instance only
|
|
13
|
+
* - Used to customize precision and other parameters
|
|
14
|
+
*/
|
|
15
|
+
decimalOptions?: DecimalOptions;
|
|
16
|
+
}
|
|
17
|
+
export declare class SmartUnitPrecision<U extends string = string> extends SmartUnitBase<U, true> {
|
|
18
|
+
private DecimalClass;
|
|
19
|
+
constructor(units: (U | number)[], option?: SmartUnitPrecisionOptions);
|
|
20
|
+
/**
|
|
21
|
+
* Gets the appropriate unit and adjusted value for the input number
|
|
22
|
+
*
|
|
23
|
+
* @param num - The input NumPrecision to determine the unit for
|
|
24
|
+
* @param fractionDigits - Decimal precision configuration
|
|
25
|
+
* @returns The FormattedValue object containing the number, unit, and decimal instance
|
|
26
|
+
*/
|
|
27
|
+
getUnit(num: NumPrecision): FormattedValuePrecision<U>;
|
|
28
|
+
/**
|
|
29
|
+
* Formats a number as a string with unit and optional decimal place configuration
|
|
30
|
+
*
|
|
31
|
+
* @param num - The input number to format
|
|
32
|
+
* @param fractionDigits - Decimal precision configuration
|
|
33
|
+
* @returns The formatted string with number and unit
|
|
34
|
+
*/
|
|
35
|
+
format(num: NumPrecision, fractionDigits?: FractionDigits): string;
|
|
36
|
+
/**
|
|
37
|
+
* Gets the chain of units for the input number
|
|
38
|
+
*
|
|
39
|
+
* @param num - The input number to determine the chain for
|
|
40
|
+
* @returns An array of FormattedValue objects representing the chain of units
|
|
41
|
+
*/
|
|
42
|
+
getChainUnit(num: NumPrecision): FormattedValuePrecision<U>[];
|
|
43
|
+
/**
|
|
44
|
+
* Formats a number as a chain of units string
|
|
45
|
+
*
|
|
46
|
+
* @param num - The input number to format
|
|
47
|
+
* @returns The formatted chain string
|
|
48
|
+
*/
|
|
49
|
+
formatChain(num: NumPrecision, separator?: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* Converts a value from the specified unit to the base unit
|
|
52
|
+
*
|
|
53
|
+
* @param num - The number to convert
|
|
54
|
+
* @param unit - The original unit of the number
|
|
55
|
+
* @returns The converted value in base unit
|
|
56
|
+
*/
|
|
57
|
+
toBase(num: NumPrecision, unit: U): Decimal;
|
|
58
|
+
/**
|
|
59
|
+
* Splits a string into its numeric part and unit
|
|
60
|
+
*
|
|
61
|
+
* @param str - Input string containing a number followed by a unit
|
|
62
|
+
* @returns An object containing the numeric value, unit, and Decimal instance
|
|
63
|
+
* @throws An error if no predefined unit is matched
|
|
64
|
+
*/
|
|
65
|
+
splitUnit(str: string): FormattedValuePrecision<U>;
|
|
66
|
+
/**
|
|
67
|
+
* Parses a string with unit into a base unit numeric value
|
|
68
|
+
*
|
|
69
|
+
* @param str - Input string containing a number and unit
|
|
70
|
+
* @returns The value converted to base unit
|
|
71
|
+
*/
|
|
72
|
+
parse(str: string): Decimal;
|
|
73
|
+
/**
|
|
74
|
+
* Converts a value from the original unit to the optimal unit with optional decimal precision
|
|
75
|
+
*
|
|
76
|
+
* @param num - The number to convert
|
|
77
|
+
* @param unit - The original unit
|
|
78
|
+
* @param fractionDigits - Optional decimal places for formatting output
|
|
79
|
+
* @returns The converted number as a formatted string
|
|
80
|
+
*/
|
|
81
|
+
fromUnitFormat(num: NumPrecision, unit: U, fractionDigits?: FractionDigits): string;
|
|
82
|
+
}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var utils = require('./utils-DqEXot5a.js');
|
|
6
|
+
|
|
7
|
+
class SmartUnit extends utils.SmartUnitBase {
|
|
8
|
+
constructor(units, option = {}) {
|
|
9
|
+
super(units, option);
|
|
10
|
+
}
|
|
11
|
+
// 根据输入数值获取单位和调整后的值
|
|
12
|
+
/**
|
|
13
|
+
* Gets the appropriate unit and adjusted value for the input number
|
|
14
|
+
*
|
|
15
|
+
* @param num - The input number to determine the unit for
|
|
16
|
+
* @param fractionDigits - Decimal precision configuration
|
|
17
|
+
* @returns The FormattedValue object containing the number, unit, and formatted number string
|
|
18
|
+
*/
|
|
19
|
+
getUnit(num, fractionDigits = this.fractionDigits) {
|
|
20
|
+
if (Number.isNaN(num))
|
|
21
|
+
throw new Error(utils.ERROR_NAN_INPUT);
|
|
22
|
+
const unitDigitsLen = this.unitDigits.length;
|
|
23
|
+
const isNegative = num < 0;
|
|
24
|
+
let absNum = isNegative ? -num : num;
|
|
25
|
+
let i = 0;
|
|
26
|
+
while (i < unitDigitsLen) {
|
|
27
|
+
const digit = this.unitDigits[i];
|
|
28
|
+
if (absNum < digit * this.threshold) {
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
absNum /= digit;
|
|
32
|
+
i++;
|
|
33
|
+
}
|
|
34
|
+
const result = isNegative ? -absNum : absNum;
|
|
35
|
+
return {
|
|
36
|
+
num: result,
|
|
37
|
+
unit: this.unitNames[i],
|
|
38
|
+
numStr: this.formatNumber(result, fractionDigits),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
// 将数字转换为字符串表示形式,并可选择配置小数位数
|
|
42
|
+
/**
|
|
43
|
+
* Formats a number as a string with unit and optional decimal place configuration
|
|
44
|
+
*
|
|
45
|
+
* @param num - The input number to format
|
|
46
|
+
* @param fractionDigits - Decimal precision configuration (defaults to instance setting)
|
|
47
|
+
* - If a number, defines fixed decimal places
|
|
48
|
+
* - If a string in "min-max" format, defines a range of decimal places
|
|
49
|
+
* - If omitted, uses the instance's default decimal configuration
|
|
50
|
+
* @returns The formatted string with number and unit (e.g. "1.50KB")
|
|
51
|
+
*/
|
|
52
|
+
format(num, fractionDigits = this.fractionDigits) {
|
|
53
|
+
const { numStr, unit } = this.getUnit(num, fractionDigits);
|
|
54
|
+
return this._format(numStr, unit);
|
|
55
|
+
}
|
|
56
|
+
// 根据输入数值获取链式单位数组
|
|
57
|
+
/**
|
|
58
|
+
* Gets the chain of units for the input number
|
|
59
|
+
* @param num - The input number to determine the chain for
|
|
60
|
+
* @returns An array of FormattedValue objects representing the chain of units
|
|
61
|
+
*/
|
|
62
|
+
getChainUnit(num) {
|
|
63
|
+
if (Number.isNaN(num))
|
|
64
|
+
throw new Error(utils.ERROR_NAN_INPUT);
|
|
65
|
+
const result = [];
|
|
66
|
+
if (num === 0) {
|
|
67
|
+
return [{ num: 0, unit: this.unitNames[0], numStr: '0' }];
|
|
68
|
+
}
|
|
69
|
+
const isNegative = num < 0;
|
|
70
|
+
let absNum = isNegative ? -num : num;
|
|
71
|
+
const accDigLen = this.accumulatedDigits.length;
|
|
72
|
+
for (let i = accDigLen - 1; i >= 0; i--) {
|
|
73
|
+
const accDigit = this.accumulatedDigits[i];
|
|
74
|
+
if (absNum < accDigit)
|
|
75
|
+
continue;
|
|
76
|
+
const res = Math.floor(absNum / accDigit);
|
|
77
|
+
const val = isNegative ? -res : res;
|
|
78
|
+
result.push({
|
|
79
|
+
num: val,
|
|
80
|
+
unit: this.unitNames[i + 1],
|
|
81
|
+
numStr: val.toString(),
|
|
82
|
+
});
|
|
83
|
+
absNum %= accDigit;
|
|
84
|
+
if (absNum === 0)
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
if (absNum !== 0) {
|
|
88
|
+
const val = isNegative ? -absNum : absNum;
|
|
89
|
+
result.push({
|
|
90
|
+
num: val,
|
|
91
|
+
unit: this.unitNames[0],
|
|
92
|
+
numStr: this.formatNumber(val, this.fractionDigits),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
// 将数字格式化为链式单位字符串
|
|
98
|
+
/**
|
|
99
|
+
* Formats a number as a chain of units string
|
|
100
|
+
* @param num - The input number to format
|
|
101
|
+
* @returns The formatted chain string
|
|
102
|
+
*/
|
|
103
|
+
formatChain(num, separator = this.separator) {
|
|
104
|
+
const chain = this.getChainUnit(num);
|
|
105
|
+
return this._formatChain(chain, separator);
|
|
106
|
+
}
|
|
107
|
+
// 将给定数值从指定单位转换为基本单位
|
|
108
|
+
/**
|
|
109
|
+
* Converts a value from the specified unit to the base unit
|
|
110
|
+
*
|
|
111
|
+
* @param num - The number to convert
|
|
112
|
+
* @param unit - The original unit of the number
|
|
113
|
+
* @returns The converted value in base unit
|
|
114
|
+
*/
|
|
115
|
+
toBase(num, unit) {
|
|
116
|
+
if (Number.isNaN(num))
|
|
117
|
+
throw new Error(utils.ERROR_NAN_INPUT);
|
|
118
|
+
const unitDigitsLen = this.unitDigits.length;
|
|
119
|
+
let nn = num;
|
|
120
|
+
for (let i = 0; i < unitDigitsLen; i++) {
|
|
121
|
+
const digit = this.unitDigits[i];
|
|
122
|
+
if (this.unitNames[i] === unit) {
|
|
123
|
+
return nn;
|
|
124
|
+
}
|
|
125
|
+
nn *= digit;
|
|
126
|
+
}
|
|
127
|
+
if (unit === this.unitNames.at(-1)) {
|
|
128
|
+
return nn;
|
|
129
|
+
}
|
|
130
|
+
throw new Error(`Undefined unit: "${unit}".`);
|
|
131
|
+
}
|
|
132
|
+
// 将带单位的值转换为基础单位的数值
|
|
133
|
+
/**
|
|
134
|
+
* Parses a string with unit into a base unit numeric value
|
|
135
|
+
*
|
|
136
|
+
* @param str - Input string containing a number and unit
|
|
137
|
+
* @returns The value converted to base unit
|
|
138
|
+
*/
|
|
139
|
+
parse(str) {
|
|
140
|
+
const { num, unit } = this.splitUnit(str);
|
|
141
|
+
return this.toBase(num, unit);
|
|
142
|
+
}
|
|
143
|
+
// 将给定数值从原单位转换为最佳单位,并可指定小数精度
|
|
144
|
+
/**
|
|
145
|
+
* Converts a value from the original unit to the optimal unit with optional decimal precision
|
|
146
|
+
*
|
|
147
|
+
* @param num - The number to convert
|
|
148
|
+
* @param unit - The original unit
|
|
149
|
+
* @param fractionDigits - Optional decimal places for formatting output
|
|
150
|
+
* @returns The converted number as a formatted string
|
|
151
|
+
*/
|
|
152
|
+
fromUnitFormat(num, unit, fractionDigits) {
|
|
153
|
+
const nnum = this.toBase(num, unit);
|
|
154
|
+
return this.format(nnum, fractionDigits);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/*!
|
|
159
|
+
* smart-unit
|
|
160
|
+
* Copyright (c) [2026] [flycran]
|
|
161
|
+
* MIT License. See LICENSE for details.
|
|
162
|
+
*/
|
|
163
|
+
|
|
164
|
+
exports.ERROR_NAN_INPUT = utils.ERROR_NAN_INPUT;
|
|
165
|
+
exports.SmartUnit = SmartUnit;
|
|
166
|
+
exports.default = SmartUnit;
|
package/dist/index.d.ts
CHANGED
|
@@ -3,108 +3,7 @@
|
|
|
3
3
|
* Copyright (c) [2026] [flycran]
|
|
4
4
|
* MIT License. See LICENSE for details.
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
export interface SmartUnitOptions<HP extends boolean = false> {
|
|
10
|
-
/** Base digit for auto-generating unit conversions */
|
|
11
|
-
baseDigit?: number;
|
|
12
|
-
/**
|
|
13
|
-
* Threshold for unit switching
|
|
14
|
-
* The comparison value is multiplied by this threshold
|
|
15
|
-
*/
|
|
16
|
-
threshold?: number;
|
|
17
|
-
/**
|
|
18
|
-
* Number of decimal places to preserve in the result
|
|
19
|
-
* Can be a fixed number or a range like "min-max"
|
|
20
|
-
*/
|
|
21
|
-
fractionDigits?: FractionDigits;
|
|
22
|
-
/**
|
|
23
|
-
* Enable high-precision calculation using decimal.js
|
|
24
|
-
* - Uses decimal.js for high-precision floating-point calculations
|
|
25
|
-
* - Supports calculations beyond JavaScript's safe integer limit
|
|
26
|
-
* - Enables string, BigInt, and Decimal inputs for format and other methods
|
|
27
|
-
*/
|
|
28
|
-
useDecimal?: HP;
|
|
29
|
-
/**
|
|
30
|
-
* Decimal.js configuration options
|
|
31
|
-
* - Creates an isolated Decimal class for this SmartUnit instance only
|
|
32
|
-
* - Used to customize precision and other parameters
|
|
33
|
-
*/
|
|
34
|
-
decimalOptions?: DecimalOptions;
|
|
35
|
-
}
|
|
36
|
-
export interface NumUnit {
|
|
37
|
-
/** The numeric value */
|
|
38
|
-
num: number;
|
|
39
|
-
/** The Decimal instance for high-precision mode */
|
|
40
|
-
decimal?: Decimal;
|
|
41
|
-
/** The unit string */
|
|
42
|
-
unit: string;
|
|
43
|
-
}
|
|
44
|
-
export type Num<DS extends boolean = false> = DS extends true ? number | bigint | string | Decimal : number;
|
|
45
|
-
export declare const ERROR_NAN_INPUT = "Accepting NaN as an argument may be unintentional and could lead to invalid results. If this is intentional, please set `SmartUnit.ignoreNaNInputs` to `true`.";
|
|
46
|
-
export declare const ERROR_HIGH_PRECISION_NOT_ENABLED = "By default, only number input is supported. To enable high-precision calculations, explicitly set the decimalSafety parameter to true.";
|
|
47
|
-
export declare class SmartUnit<HP extends boolean = false> {
|
|
48
|
-
readonly units: (string | number)[];
|
|
49
|
-
static ignoreNaNInputs: boolean;
|
|
50
|
-
readonly threshold: number;
|
|
51
|
-
readonly decimal?: FractionDigits;
|
|
52
|
-
readonly unitsStr: string[];
|
|
53
|
-
readonly highPrecision: HP;
|
|
54
|
-
private DecimalClass;
|
|
55
|
-
constructor(units: (string | number)[], option?: SmartUnitOptions<HP>);
|
|
56
|
-
/**
|
|
57
|
-
* Gets the appropriate unit and adjusted value for the input number
|
|
58
|
-
*
|
|
59
|
-
* @param num - The input number to determine the unit for
|
|
60
|
-
* @returns An object containing the adjusted number and its corresponding unit
|
|
61
|
-
*/
|
|
62
|
-
getUnit(num: Num<HP>): NumUnit;
|
|
63
|
-
/**
|
|
64
|
-
* Formats a number as a string with optional decimal place configuration
|
|
65
|
-
*
|
|
66
|
-
* @param num - The number to convert to string
|
|
67
|
-
* @param decimal - Decimal precision configuration (defaults to instance setting)
|
|
68
|
-
* - If a number, defines fixed decimal places
|
|
69
|
-
* - If a string in "min-max" format, defines a range of decimal places
|
|
70
|
-
* - If omitted, uses the instance's default decimal configuration
|
|
71
|
-
* @returns The formatted string representation with unit
|
|
72
|
-
*/
|
|
73
|
-
format(num: Num<HP>, decimal?: FractionDigits): string;
|
|
74
|
-
/**
|
|
75
|
-
* Converts a value from the specified unit to the base unit
|
|
76
|
-
*
|
|
77
|
-
* @param num - The number to convert
|
|
78
|
-
* @param unit - The original unit of the number
|
|
79
|
-
* @returns The converted value in base unit
|
|
80
|
-
* - Returns Decimal if high-precision mode is enabled
|
|
81
|
-
*/
|
|
82
|
-
toBase(num: Num<HP>, unit: string): HP extends true ? Decimal : number;
|
|
83
|
-
/**
|
|
84
|
-
* Splits a string into its numeric part and unit
|
|
85
|
-
*
|
|
86
|
-
* @param str - Input string containing a number followed by a unit
|
|
87
|
-
* @returns An object containing the numeric value and unit
|
|
88
|
-
* Only supports predefined units
|
|
89
|
-
* Throws an error if no match is found
|
|
90
|
-
*/
|
|
91
|
-
splitUnit(str: string): NumUnit;
|
|
92
|
-
/**
|
|
93
|
-
* Parses a string with unit into a base unit numeric value
|
|
94
|
-
*
|
|
95
|
-
* @param str - Input string containing a number and unit
|
|
96
|
-
* @returns The value converted to base unit
|
|
97
|
-
* - Returns Decimal if high-precision mode is enabled
|
|
98
|
-
*/
|
|
99
|
-
parse(str: string): HP extends true ? Decimal : number;
|
|
100
|
-
/**
|
|
101
|
-
* Converts a value from the original unit to the optimal unit with optional decimal precision
|
|
102
|
-
*
|
|
103
|
-
* @param num - The number to convert
|
|
104
|
-
* @param unit - The original unit
|
|
105
|
-
* @param decimal - Optional decimal places for formatting output
|
|
106
|
-
* @returns The converted number as a formatted string
|
|
107
|
-
*/
|
|
108
|
-
fromUnitFormat(num: Num<HP>, unit: string, decimal?: FractionDigits): string;
|
|
109
|
-
}
|
|
6
|
+
export * from './SmartUnit';
|
|
7
|
+
export * from './utils';
|
|
8
|
+
import { SmartUnit } from './SmartUnit';
|
|
110
9
|
export default SmartUnit;
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { S as SmartUnitBase, E as ERROR_NAN_INPUT } from './utils-C1byK7Uk.js';
|
|
2
|
+
|
|
3
|
+
class SmartUnit extends SmartUnitBase {
|
|
4
|
+
constructor(units, option = {}) {
|
|
5
|
+
super(units, option);
|
|
6
|
+
}
|
|
7
|
+
// 根据输入数值获取单位和调整后的值
|
|
8
|
+
/**
|
|
9
|
+
* Gets the appropriate unit and adjusted value for the input number
|
|
10
|
+
*
|
|
11
|
+
* @param num - The input number to determine the unit for
|
|
12
|
+
* @param fractionDigits - Decimal precision configuration
|
|
13
|
+
* @returns The FormattedValue object containing the number, unit, and formatted number string
|
|
14
|
+
*/
|
|
15
|
+
getUnit(num, fractionDigits = this.fractionDigits) {
|
|
16
|
+
if (Number.isNaN(num))
|
|
17
|
+
throw new Error(ERROR_NAN_INPUT);
|
|
18
|
+
const unitDigitsLen = this.unitDigits.length;
|
|
19
|
+
const isNegative = num < 0;
|
|
20
|
+
let absNum = isNegative ? -num : num;
|
|
21
|
+
let i = 0;
|
|
22
|
+
while (i < unitDigitsLen) {
|
|
23
|
+
const digit = this.unitDigits[i];
|
|
24
|
+
if (absNum < digit * this.threshold) {
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
absNum /= digit;
|
|
28
|
+
i++;
|
|
29
|
+
}
|
|
30
|
+
const result = isNegative ? -absNum : absNum;
|
|
31
|
+
return {
|
|
32
|
+
num: result,
|
|
33
|
+
unit: this.unitNames[i],
|
|
34
|
+
numStr: this.formatNumber(result, fractionDigits),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
// 将数字转换为字符串表示形式,并可选择配置小数位数
|
|
38
|
+
/**
|
|
39
|
+
* Formats a number as a string with unit and optional decimal place configuration
|
|
40
|
+
*
|
|
41
|
+
* @param num - The input number to format
|
|
42
|
+
* @param fractionDigits - Decimal precision configuration (defaults to instance setting)
|
|
43
|
+
* - If a number, defines fixed decimal places
|
|
44
|
+
* - If a string in "min-max" format, defines a range of decimal places
|
|
45
|
+
* - If omitted, uses the instance's default decimal configuration
|
|
46
|
+
* @returns The formatted string with number and unit (e.g. "1.50KB")
|
|
47
|
+
*/
|
|
48
|
+
format(num, fractionDigits = this.fractionDigits) {
|
|
49
|
+
const { numStr, unit } = this.getUnit(num, fractionDigits);
|
|
50
|
+
return this._format(numStr, unit);
|
|
51
|
+
}
|
|
52
|
+
// 根据输入数值获取链式单位数组
|
|
53
|
+
/**
|
|
54
|
+
* Gets the chain of units for the input number
|
|
55
|
+
* @param num - The input number to determine the chain for
|
|
56
|
+
* @returns An array of FormattedValue objects representing the chain of units
|
|
57
|
+
*/
|
|
58
|
+
getChainUnit(num) {
|
|
59
|
+
if (Number.isNaN(num))
|
|
60
|
+
throw new Error(ERROR_NAN_INPUT);
|
|
61
|
+
const result = [];
|
|
62
|
+
if (num === 0) {
|
|
63
|
+
return [{ num: 0, unit: this.unitNames[0], numStr: '0' }];
|
|
64
|
+
}
|
|
65
|
+
const isNegative = num < 0;
|
|
66
|
+
let absNum = isNegative ? -num : num;
|
|
67
|
+
const accDigLen = this.accumulatedDigits.length;
|
|
68
|
+
for (let i = accDigLen - 1; i >= 0; i--) {
|
|
69
|
+
const accDigit = this.accumulatedDigits[i];
|
|
70
|
+
if (absNum < accDigit)
|
|
71
|
+
continue;
|
|
72
|
+
const res = Math.floor(absNum / accDigit);
|
|
73
|
+
const val = isNegative ? -res : res;
|
|
74
|
+
result.push({
|
|
75
|
+
num: val,
|
|
76
|
+
unit: this.unitNames[i + 1],
|
|
77
|
+
numStr: val.toString(),
|
|
78
|
+
});
|
|
79
|
+
absNum %= accDigit;
|
|
80
|
+
if (absNum === 0)
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
if (absNum !== 0) {
|
|
84
|
+
const val = isNegative ? -absNum : absNum;
|
|
85
|
+
result.push({
|
|
86
|
+
num: val,
|
|
87
|
+
unit: this.unitNames[0],
|
|
88
|
+
numStr: this.formatNumber(val, this.fractionDigits),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
// 将数字格式化为链式单位字符串
|
|
94
|
+
/**
|
|
95
|
+
* Formats a number as a chain of units string
|
|
96
|
+
* @param num - The input number to format
|
|
97
|
+
* @returns The formatted chain string
|
|
98
|
+
*/
|
|
99
|
+
formatChain(num, separator = this.separator) {
|
|
100
|
+
const chain = this.getChainUnit(num);
|
|
101
|
+
return this._formatChain(chain, separator);
|
|
102
|
+
}
|
|
103
|
+
// 将给定数值从指定单位转换为基本单位
|
|
104
|
+
/**
|
|
105
|
+
* Converts a value from the specified unit to the base unit
|
|
106
|
+
*
|
|
107
|
+
* @param num - The number to convert
|
|
108
|
+
* @param unit - The original unit of the number
|
|
109
|
+
* @returns The converted value in base unit
|
|
110
|
+
*/
|
|
111
|
+
toBase(num, unit) {
|
|
112
|
+
if (Number.isNaN(num))
|
|
113
|
+
throw new Error(ERROR_NAN_INPUT);
|
|
114
|
+
const unitDigitsLen = this.unitDigits.length;
|
|
115
|
+
let nn = num;
|
|
116
|
+
for (let i = 0; i < unitDigitsLen; i++) {
|
|
117
|
+
const digit = this.unitDigits[i];
|
|
118
|
+
if (this.unitNames[i] === unit) {
|
|
119
|
+
return nn;
|
|
120
|
+
}
|
|
121
|
+
nn *= digit;
|
|
122
|
+
}
|
|
123
|
+
if (unit === this.unitNames.at(-1)) {
|
|
124
|
+
return nn;
|
|
125
|
+
}
|
|
126
|
+
throw new Error(`Undefined unit: "${unit}".`);
|
|
127
|
+
}
|
|
128
|
+
// 将带单位的值转换为基础单位的数值
|
|
129
|
+
/**
|
|
130
|
+
* Parses a string with unit into a base unit numeric value
|
|
131
|
+
*
|
|
132
|
+
* @param str - Input string containing a number and unit
|
|
133
|
+
* @returns The value converted to base unit
|
|
134
|
+
*/
|
|
135
|
+
parse(str) {
|
|
136
|
+
const { num, unit } = this.splitUnit(str);
|
|
137
|
+
return this.toBase(num, unit);
|
|
138
|
+
}
|
|
139
|
+
// 将给定数值从原单位转换为最佳单位,并可指定小数精度
|
|
140
|
+
/**
|
|
141
|
+
* Converts a value from the original unit to the optimal unit with optional decimal precision
|
|
142
|
+
*
|
|
143
|
+
* @param num - The number to convert
|
|
144
|
+
* @param unit - The original unit
|
|
145
|
+
* @param fractionDigits - Optional decimal places for formatting output
|
|
146
|
+
* @returns The converted number as a formatted string
|
|
147
|
+
*/
|
|
148
|
+
fromUnitFormat(num, unit, fractionDigits) {
|
|
149
|
+
const nnum = this.toBase(num, unit);
|
|
150
|
+
return this.format(nnum, fractionDigits);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/*!
|
|
155
|
+
* smart-unit
|
|
156
|
+
* Copyright (c) [2026] [flycran]
|
|
157
|
+
* MIT License. See LICENSE for details.
|
|
158
|
+
*/
|
|
159
|
+
|
|
160
|
+
export { ERROR_NAN_INPUT, SmartUnit, SmartUnit as default };
|