@canvas-components/utils 0.2.1 → 0.2.2
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 +130 -103
- package/dist/date/index.cjs +162 -0
- package/dist/date/index.cjs.map +1 -0
- package/dist/date/index.d.cts +13 -0
- package/dist/date/index.d.ts +13 -0
- package/dist/date/index.js +158 -0
- package/dist/date/index.js.map +1 -0
- package/dist/index.cjs +553 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +537 -1
- package/dist/index.js.map +1 -1
- package/dist/number/index.cjs +399 -0
- package/dist/number/index.cjs.map +1 -0
- package/dist/number/index.d.cts +44 -0
- package/dist/number/index.d.ts +44 -0
- package/dist/number/index.js +384 -0
- package/dist/number/index.js.map +1 -0
- package/package.json +11 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/number/precise.ts","../../src/number/index.ts"],"names":["digit"],"mappings":"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","file":"index.cjs","sourcesContent":["/** 可参与精确十进制计算的值。字符串可保留超出 Number 安全范围的整数精度。 */\r\nexport type PreciseNumberInput = string | number | bigint;\r\nexport type PreciseRoundingMode = \"round\" | \"floor\" | \"ceil\" | \"truncate\";\r\n\r\ninterface DecimalParts {\r\n coefficient: bigint;\r\n scale: number;\r\n}\r\n\r\n/** 精确相加两个十进制数,非法或非有限输入返回 null。 */\r\nexport function addPreciseNumbers(\r\n left: PreciseNumberInput,\r\n right: PreciseNumberInput,\r\n): string | null {\r\n const leftParts = parseDecimal(left);\r\n const rightParts = parseDecimal(right);\r\n if (!leftParts || !rightParts) return null;\r\n return formatDecimal(addParts(leftParts, rightParts));\r\n}\r\n\r\n/** 精确累加一组十进制数,非法值跳过且没有有效值时返回 null。 */\r\nexport function sumPreciseNumbers(\r\n values: Iterable<PreciseNumberInput>,\r\n): string | null {\r\n let result: DecimalParts = { coefficient: 0n, scale: 0 };\r\n let count = 0;\r\n for (const value of values) {\r\n const parts = parseDecimal(value);\r\n if (!parts) continue;\r\n result = addParts(result, parts);\r\n count += 1;\r\n }\r\n return count === 0 ? null : formatDecimal(result);\r\n}\r\n\r\n/** 比较两个十进制数,返回 -1、0、1;非法输入返回 null。 */\r\nexport function comparePreciseNumbers(\r\n left: PreciseNumberInput,\r\n right: PreciseNumberInput,\r\n): -1 | 0 | 1 | null {\r\n const leftParts = parseDecimal(left);\r\n const rightParts = parseDecimal(right);\r\n if (!leftParts || !rightParts) return null;\r\n const scale = Math.max(leftParts.scale, rightParts.scale);\r\n const leftValue =\r\n leftParts.coefficient * 10n ** BigInt(scale - leftParts.scale);\r\n const rightValue =\r\n rightParts.coefficient * 10n ** BigInt(scale - rightParts.scale);\r\n return leftValue < rightValue ? -1 : leftValue > rightValue ? 1 : 0;\r\n}\r\n\r\n/** 精确除法并按指定小数位四舍五入。 */\r\nexport function dividePreciseNumber(\r\n value: PreciseNumberInput,\r\n divisor: PreciseNumberInput,\r\n precision = 20,\r\n): string | null {\r\n const valueParts = parseDecimal(value);\r\n const divisorParts = parseDecimal(divisor);\r\n if (!valueParts || !divisorParts || divisorParts.coefficient === 0n)\r\n return null;\r\n const places = normalizePrecision(precision);\r\n const scale = places + divisorParts.scale - valueParts.scale;\r\n const factor = 10n ** BigInt(Math.max(scale, 0));\r\n const numerator = valueParts.coefficient * factor;\r\n const denominator = divisorParts.coefficient;\r\n const quotient = numerator / denominator;\r\n const remainder = numerator % denominator;\r\n const rounded =\r\n remainder === 0n\r\n ? quotient\r\n : quotient +\r\n (numerator < 0n === denominator < 0n ? 1n : -1n) *\r\n (abs(remainder) * 2n >= abs(denominator) ? 1n : 0n);\r\n return formatDecimal({ coefficient: rounded, scale: Math.max(places, 0) });\r\n}\r\n\r\n/** 对十进制数进行四舍五入并保留指定小数位。 */\r\nexport function roundPreciseNumber(\r\n value: PreciseNumberInput,\r\n precision: number,\r\n mode: PreciseRoundingMode = \"round\",\r\n): string | null {\r\n const parts = parseDecimal(value);\r\n if (!parts) return null;\r\n const places = normalizePrecision(precision);\r\n if (parts.scale <= places)\r\n return formatDecimal(\r\n {\r\n ...parts,\r\n coefficient: parts.coefficient * 10n ** BigInt(places - parts.scale),\r\n },\r\n places,\r\n );\r\n const factor = 10n ** BigInt(parts.scale - places);\r\n let quotient = parts.coefficient / factor;\r\n const remainder = parts.coefficient % factor;\r\n if (remainder !== 0n) {\r\n const isNegative = parts.coefficient < 0n;\r\n const direction = isNegative ? -1n : 1n;\r\n if (\r\n (mode === \"ceil\" && !isNegative) ||\r\n (mode === \"floor\" && isNegative) ||\r\n (mode === \"round\" && abs(remainder) * 2n >= factor)\r\n ) {\r\n quotient += direction;\r\n }\r\n }\r\n return formatDecimal({ coefficient: quotient, scale: places }, places);\r\n}\r\n\r\n/** 格式化十进制数,可选择保留输入值的尾随零。 */\r\nexport function formatPreciseNumber(\r\n value: PreciseNumberInput,\r\n precision?: number,\r\n preserveTrailingZeros = false,\r\n): string | null {\r\n const parts = parseDecimal(value);\r\n if (!parts) return null;\r\n return precision == null\r\n ? formatDecimal(parts, preserveTrailingZeros ? parts.scale : 0)\r\n : roundPreciseNumber(value, precision);\r\n}\r\n\r\nfunction parseDecimal(value: PreciseNumberInput): DecimalParts | null {\r\n if (typeof value === \"number\") {\r\n if (!Number.isFinite(value)) return null;\r\n value = String(value);\r\n } else if (typeof value === \"bigint\") {\r\n return { coefficient: value, scale: 0 };\r\n }\r\n const match = value\r\n .trim()\r\n .match(/^([+-]?)(\\d+)(?:\\.(\\d*))?(?:e([+-]?\\d+))?$/i);\r\n if (!match) return null;\r\n const fraction = match[3] ?? \"\";\r\n const exponent = Number(match[4] ?? 0);\r\n if (!Number.isSafeInteger(exponent)) return null;\r\n const scale = fraction.length - exponent;\r\n const coefficient = BigInt(\r\n `${match[1] === \"-\" ? \"-\" : \"\"}${match[2]}${fraction}`,\r\n );\r\n return scale >= 0\r\n ? { coefficient, scale }\r\n : { coefficient: coefficient * 10n ** BigInt(-scale), scale: 0 };\r\n}\r\n\r\nfunction addParts(left: DecimalParts, right: DecimalParts): DecimalParts {\r\n const scale = Math.max(left.scale, right.scale);\r\n return {\r\n coefficient:\r\n left.coefficient * 10n ** BigInt(scale - left.scale) +\r\n right.coefficient * 10n ** BigInt(scale - right.scale),\r\n scale,\r\n };\r\n}\r\n\r\nfunction formatDecimal(parts: DecimalParts, minimumScale = 0): string {\r\n const negative = parts.coefficient < 0n;\r\n const digits = abs(parts.coefficient)\r\n .toString()\r\n .padStart(parts.scale + 1, \"0\");\r\n const scale = Math.max(parts.scale, minimumScale);\r\n const padded = digits.padStart(scale + 1, \"0\");\r\n const integer = padded.slice(0, -scale || undefined) || \"0\";\r\n const fraction = scale > 0 ? padded.slice(-scale).padEnd(scale, \"0\") : \"\";\r\n const displayFraction =\r\n minimumScale > 0 ? fraction : fraction.replace(/0+$/, \"\");\r\n return `${negative ? \"-\" : \"\"}${integer}${displayFraction ? `.${displayFraction}` : \"\"}`;\r\n}\r\n\r\nfunction normalizePrecision(value: number) {\r\n return Math.min(\r\n 100,\r\n Math.max(0, Math.trunc(Number.isFinite(value) ? value : 20)),\r\n );\r\n}\r\n\r\nfunction abs(value: bigint) {\r\n return value < 0n ? -value : value;\r\n}\r\n","/** 通用数字格式化选项。 */\r\nexport interface NumberFormatOptions {\r\n /** 小数位数;`\"auto\"` 表示保留原始小数位。 */\r\n decimalPlaces?: number | \"auto\";\r\n /** 是否使用千分位分隔符,传入字符串时作为分隔符。 */\r\n thousandsSeparator?: boolean | string;\r\n /** 前置符号,例如 `¥` 或 `$`。 */\r\n symbol?: string;\r\n}\r\n\r\nexport type ChineseNumberStyle = \"common\" | \"financial\";\r\n\r\nconst COMMON_CHINESE_DIGITS = [\r\n \"零\",\r\n \"一\",\r\n \"二\",\r\n \"三\",\r\n \"四\",\r\n \"五\",\r\n \"六\",\r\n \"七\",\r\n \"八\",\r\n \"九\",\r\n];\r\nconst FINANCIAL_CHINESE_DIGITS = [\r\n \"零\",\r\n \"壹\",\r\n \"贰\",\r\n \"叁\",\r\n \"肆\",\r\n \"伍\",\r\n \"陆\",\r\n \"柒\",\r\n \"捌\",\r\n \"玖\",\r\n];\r\nconst COMMON_SECTION_UNITS = [\"\", \"十\", \"百\", \"千\"];\r\nconst FINANCIAL_SECTION_UNITS = [\"\", \"拾\", \"佰\", \"仟\"];\r\nconst LARGE_CHINESE_UNITS = [\"\", \"万\", \"亿\", \"兆\", \"京\"];\r\n\r\nconst CHINESE_DIGIT_VALUES: Record<string, number> = {\r\n 零: 0,\r\n 〇: 0,\r\n 一: 1,\r\n 壹: 1,\r\n 二: 2,\r\n 贰: 2,\r\n 貳: 2,\r\n 两: 2,\r\n 兩: 2,\r\n 三: 3,\r\n 叁: 3,\r\n 參: 3,\r\n 四: 4,\r\n 肆: 4,\r\n 五: 5,\r\n 伍: 5,\r\n 六: 6,\r\n 陆: 6,\r\n 陸: 6,\r\n 七: 7,\r\n 柒: 7,\r\n 八: 8,\r\n 捌: 8,\r\n 九: 9,\r\n 玖: 9,\r\n};\r\n\r\nconst CHINESE_SMALL_UNIT_VALUES: Record<string, number> = {\r\n 十: 10,\r\n 拾: 10,\r\n 百: 100,\r\n 佰: 100,\r\n 千: 1000,\r\n 仟: 1000,\r\n};\r\n\r\nconst CHINESE_LARGE_UNIT_VALUES: Record<string, number> = {\r\n 万: 10_000,\r\n 萬: 10_000,\r\n 亿: 100_000_000,\r\n 億: 100_000_000,\r\n 兆: 1_000_000_000_000,\r\n};\r\n\r\n/** 将数字、带千分位数字字符串解析为有限数字。 */\r\nexport function parseNumberValue(value: unknown): number | null {\r\n if (typeof value === \"number\") return Number.isFinite(value) ? value : null;\r\n if (typeof value !== \"string\") return null;\r\n const normalized = value.trim().replace(/,/g, \"\");\r\n if (!normalized) return null;\r\n const numericValue = Number(normalized);\r\n return Number.isFinite(numericValue) ? numericValue : null;\r\n}\r\n\r\n/** 限制小数位数到 0 到 20。 */\r\nexport function normalizeDecimalPlaces(\r\n decimalPlaces: number | undefined,\r\n fallback = 2,\r\n) {\r\n if (typeof decimalPlaces !== \"number\" || !Number.isFinite(decimalPlaces)) {\r\n return fallback;\r\n }\r\n return Math.min(20, Math.max(Math.trunc(decimalPlaces), 0));\r\n}\r\n\r\n/** 格式化数字、金额和千分位数字。 */\r\nexport function formatNumberValue(\r\n value: unknown,\r\n options: NumberFormatOptions = {},\r\n) {\r\n if (value == null || value === \"\") return \"\";\r\n const numericValue = parseNumberValue(value);\r\n if (numericValue == null) return String(value);\r\n const separator = resolveThousandsSeparator(options.thousandsSeparator);\r\n const decimalPlaces =\r\n options.decimalPlaces === \"auto\"\r\n ? undefined\r\n : normalizeDecimalPlaces(options.decimalPlaces);\r\n const absoluteText =\r\n decimalPlaces == null\r\n ? String(Math.abs(numericValue))\r\n : Math.abs(numericValue).toFixed(decimalPlaces);\r\n const [integerText = \"0\", decimalText] = absoluteText.split(\".\");\r\n const formattedInteger = separator\r\n ? integerText.replace(/\\B(?=(\\d{3})+(?!\\d))/g, separator)\r\n : integerText;\r\n const sign = numericValue < 0 ? \"-\" : \"\";\r\n return `${sign}${options.symbol ?? \"\"}${formattedInteger}${decimalText ? `.${decimalText}` : \"\"}`;\r\n}\r\n\r\n/** 格式化百分比数值,输入 `0.125` 输出 `12.5%`。 */\r\nexport function formatPercentValue(value: unknown, decimalPlaces = 2) {\r\n const numericValue = parseNumberValue(value);\r\n if (numericValue == null) return String(value ?? \"\");\r\n return `${(numericValue * 100).toFixed(normalizeDecimalPlaces(decimalPlaces))}%`;\r\n}\r\n\r\n/** 格式化科学计数法,指数固定补足三位。 */\r\nexport function formatScientificValue(value: unknown, decimalPlaces = 2) {\r\n const numericValue = parseNumberValue(value);\r\n if (numericValue == null) return String(value ?? \"\");\r\n const [mantissa, exponentText] = numericValue\r\n .toExponential(normalizeDecimalPlaces(decimalPlaces))\r\n .split(\"e\");\r\n const exponent = Number(exponentText ?? 0);\r\n return `${mantissa}E${exponent >= 0 ? \"+\" : \"-\"}${String(Math.abs(exponent)).padStart(3, \"0\")}`;\r\n}\r\n\r\n/** 按常见表格数字 pattern 格式化自定义数字。 */\r\nexport function formatCustomNumberPattern(value: unknown, pattern: string) {\r\n if (pattern.includes(\"@\") || pattern.includes(\"通用格式\")) {\r\n return String(value ?? \"\");\r\n }\r\n const literalOnly = pattern.match(/^\"([^\"]*)\"$/);\r\n if (literalOnly) return literalOnly[1] ?? \"\";\r\n const numericValue = parseNumberValue(value);\r\n if (numericValue == null) return String(value ?? \"\");\r\n const percent = pattern.includes(\"%\");\r\n const tenThousands = pattern.includes(\"万\");\r\n const decimalPlaces = pattern.match(/\\.(0+)/)?.[1]?.length ?? 0;\r\n const scaled =\r\n (numericValue * (percent ? 100 : 1)) / (tenThousands ? 10_000 : 1);\r\n const symbol = pattern.includes(\"¥\") ? \"¥\" : pattern.includes(\"$\") ? \"$\" : \"\";\r\n if (/e\\+/i.test(pattern)) return formatScientificValue(scaled, decimalPlaces);\r\n const text = formatNumberValue(scaled, {\r\n decimalPlaces,\r\n thousandsSeparator: pattern.includes(\",\") && !tenThousands,\r\n symbol,\r\n });\r\n return `${text}${tenThousands ? \"万\" : \"\"}${percent ? \"%\" : \"\"}`;\r\n}\r\n\r\n/** 将阿拉伯数字或中文数字转换为中文数字。 */\r\nexport function formatChineseNumber(\r\n value: unknown,\r\n style: ChineseNumberStyle = \"financial\",\r\n): string | null {\r\n const numericValue =\r\n parseNumberValue(value) ??\r\n (typeof value === \"string\" ? parseChineseNumber(value) : null);\r\n if (numericValue == null || !Number.isFinite(numericValue)) return null;\r\n const negative = numericValue < 0;\r\n const absoluteValue = Math.abs(numericValue);\r\n const [integerText, decimalText = \"\"] =\r\n toPlainNumberText(absoluteValue).split(\".\");\r\n const digits =\r\n style === \"financial\" ? FINANCIAL_CHINESE_DIGITS : COMMON_CHINESE_DIGITS;\r\n const sectionUnits =\r\n style === \"financial\" ? FINANCIAL_SECTION_UNITS : COMMON_SECTION_UNITS;\r\n const integerResult = formatChineseInteger(\r\n integerText ?? \"0\",\r\n digits,\r\n sectionUnits,\r\n );\r\n const decimalResult = decimalText\r\n ? `点${Array.from(decimalText, (digit) => digits[Number(digit)] ?? \"\").join(\"\")}`\r\n : \"\";\r\n return `${negative ? \"负\" : \"\"}${integerResult}${decimalResult}`;\r\n}\r\n\r\n/** 将普通中文数字或金融大写数字解析为阿拉伯数字。 */\r\nexport function parseChineseNumber(value: unknown): number | null {\r\n if (typeof value === \"number\") return Number.isFinite(value) ? value : null;\r\n if (typeof value !== \"string\") return null;\r\n let source = value.trim().replace(/[\\s,,]/g, \"\");\r\n if (!source) return null;\r\n const negative = source.startsWith(\"负\") || source.startsWith(\"-\");\r\n if (negative) source = source.slice(1);\r\n const [integerSource = \"\", decimalSource] = source.split(/[点\\.]/, 2);\r\n if (!integerSource) return null;\r\n const integerValue = parseChineseInteger(integerSource);\r\n if (integerValue == null) return null;\r\n let decimalValue = 0;\r\n if (decimalSource) {\r\n let scale = 0.1;\r\n for (const character of decimalSource) {\r\n const digit = resolveChineseDigit(character);\r\n if (digit == null) return null;\r\n decimalValue += digit * scale;\r\n scale /= 10;\r\n }\r\n }\r\n const result = integerValue + decimalValue;\r\n return negative ? -result : result;\r\n}\r\n\r\nfunction formatChineseInteger(\r\n integerText: string,\r\n digits: string[],\r\n sectionUnits: string[],\r\n) {\r\n const normalized = integerText.replace(/^0+(?=\\d)/, \"\");\r\n if (normalized === \"0\") return digits[0] ?? \"零\";\r\n const sections: number[] = [];\r\n for (let end = normalized.length; end > 0; end -= 4) {\r\n sections.push(Number(normalized.slice(Math.max(0, end - 4), end)));\r\n }\r\n let result = \"\";\r\n let pendingZero = false;\r\n for (let index = sections.length - 1; index >= 0; index -= 1) {\r\n const section = sections[index] ?? 0;\r\n if (section === 0) {\r\n if (result) pendingZero = true;\r\n continue;\r\n }\r\n if (result && (pendingZero || section < 1000)) result += digits[0] ?? \"零\";\r\n result += formatChineseSection(section, digits, sectionUnits);\r\n result += LARGE_CHINESE_UNITS[index] ?? \"\";\r\n pendingZero = false;\r\n }\r\n return digits === COMMON_CHINESE_DIGITS && result.startsWith(\"一十\")\r\n ? result.slice(1)\r\n : result;\r\n}\r\n\r\nfunction formatChineseSection(\r\n section: number,\r\n digits: string[],\r\n sectionUnits: string[],\r\n) {\r\n let result = \"\";\r\n let pendingZero = false;\r\n for (let position = 3; position >= 0; position -= 1) {\r\n const unitValue = 10 ** position;\r\n const digit = Math.floor(section / unitValue) % 10;\r\n if (digit === 0) {\r\n if (result && section % unitValue !== 0) pendingZero = true;\r\n continue;\r\n }\r\n if (pendingZero) result += digits[0] ?? \"零\";\r\n result += `${digits[digit] ?? \"\"}${sectionUnits[position] ?? \"\"}`;\r\n pendingZero = false;\r\n }\r\n return result;\r\n}\r\n\r\nfunction parseChineseInteger(source: string) {\r\n const hasUnit = Array.from(source).some(\r\n (character) =>\r\n character in CHINESE_SMALL_UNIT_VALUES ||\r\n character in CHINESE_LARGE_UNIT_VALUES,\r\n );\r\n if (!hasUnit) {\r\n let text = \"\";\r\n for (const character of source) {\r\n const digit = resolveChineseDigit(character);\r\n if (digit == null) return null;\r\n text += String(digit);\r\n }\r\n return text ? Number(text) : null;\r\n }\r\n let total = 0;\r\n let section = 0;\r\n let digit: number | null = null;\r\n for (const character of source) {\r\n const digitValue = resolveChineseDigit(character);\r\n if (digitValue != null) {\r\n digit = digitValue;\r\n continue;\r\n }\r\n const smallUnit = CHINESE_SMALL_UNIT_VALUES[character];\r\n if (smallUnit) {\r\n section += (digit ?? 1) * smallUnit;\r\n digit = null;\r\n continue;\r\n }\r\n const largeUnit = CHINESE_LARGE_UNIT_VALUES[character];\r\n if (largeUnit) {\r\n section += digit ?? 0;\r\n total += section * largeUnit;\r\n section = 0;\r\n digit = null;\r\n continue;\r\n }\r\n return null;\r\n }\r\n return total + section + (digit ?? 0);\r\n}\r\n\r\nfunction resolveChineseDigit(character: string) {\r\n if (/\\d/.test(character)) return Number(character);\r\n return CHINESE_DIGIT_VALUES[character] ?? null;\r\n}\r\n\r\nfunction toPlainNumberText(value: number) {\r\n const source = String(value);\r\n if (!/[eE]/.test(source)) return source;\r\n return value.toLocaleString(\"en-US\", {\r\n useGrouping: false,\r\n maximumFractionDigits: 20,\r\n });\r\n}\r\n\r\nfunction resolveThousandsSeparator(separator: boolean | string | undefined) {\r\n if (separator == null || separator === false) return \"\";\r\n if (typeof separator === \"string\") return separator;\r\n return \",\";\r\n}\r\nexport {\r\n addPreciseNumbers,\r\n comparePreciseNumbers,\r\n dividePreciseNumber,\r\n formatPreciseNumber,\r\n roundPreciseNumber,\r\n sumPreciseNumbers,\r\n} from \"./precise\";\r\nexport type { PreciseNumberInput } from \"./precise\";\r\nexport type { PreciseRoundingMode } from \"./precise\";\r\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** 可参与精确十进制计算的值。字符串可保留超出 Number 安全范围的整数精度。 */
|
|
2
|
+
type PreciseNumberInput = string | number | bigint;
|
|
3
|
+
type PreciseRoundingMode = "round" | "floor" | "ceil" | "truncate";
|
|
4
|
+
/** 精确相加两个十进制数,非法或非有限输入返回 null。 */
|
|
5
|
+
declare function addPreciseNumbers(left: PreciseNumberInput, right: PreciseNumberInput): string | null;
|
|
6
|
+
/** 精确累加一组十进制数,非法值跳过且没有有效值时返回 null。 */
|
|
7
|
+
declare function sumPreciseNumbers(values: Iterable<PreciseNumberInput>): string | null;
|
|
8
|
+
/** 比较两个十进制数,返回 -1、0、1;非法输入返回 null。 */
|
|
9
|
+
declare function comparePreciseNumbers(left: PreciseNumberInput, right: PreciseNumberInput): -1 | 0 | 1 | null;
|
|
10
|
+
/** 精确除法并按指定小数位四舍五入。 */
|
|
11
|
+
declare function dividePreciseNumber(value: PreciseNumberInput, divisor: PreciseNumberInput, precision?: number): string | null;
|
|
12
|
+
/** 对十进制数进行四舍五入并保留指定小数位。 */
|
|
13
|
+
declare function roundPreciseNumber(value: PreciseNumberInput, precision: number, mode?: PreciseRoundingMode): string | null;
|
|
14
|
+
/** 格式化十进制数,可选择保留输入值的尾随零。 */
|
|
15
|
+
declare function formatPreciseNumber(value: PreciseNumberInput, precision?: number, preserveTrailingZeros?: boolean): string | null;
|
|
16
|
+
|
|
17
|
+
/** 通用数字格式化选项。 */
|
|
18
|
+
interface NumberFormatOptions {
|
|
19
|
+
/** 小数位数;`"auto"` 表示保留原始小数位。 */
|
|
20
|
+
decimalPlaces?: number | "auto";
|
|
21
|
+
/** 是否使用千分位分隔符,传入字符串时作为分隔符。 */
|
|
22
|
+
thousandsSeparator?: boolean | string;
|
|
23
|
+
/** 前置符号,例如 `¥` 或 `$`。 */
|
|
24
|
+
symbol?: string;
|
|
25
|
+
}
|
|
26
|
+
type ChineseNumberStyle = "common" | "financial";
|
|
27
|
+
/** 将数字、带千分位数字字符串解析为有限数字。 */
|
|
28
|
+
declare function parseNumberValue(value: unknown): number | null;
|
|
29
|
+
/** 限制小数位数到 0 到 20。 */
|
|
30
|
+
declare function normalizeDecimalPlaces(decimalPlaces: number | undefined, fallback?: number): number;
|
|
31
|
+
/** 格式化数字、金额和千分位数字。 */
|
|
32
|
+
declare function formatNumberValue(value: unknown, options?: NumberFormatOptions): string;
|
|
33
|
+
/** 格式化百分比数值,输入 `0.125` 输出 `12.5%`。 */
|
|
34
|
+
declare function formatPercentValue(value: unknown, decimalPlaces?: number): string;
|
|
35
|
+
/** 格式化科学计数法,指数固定补足三位。 */
|
|
36
|
+
declare function formatScientificValue(value: unknown, decimalPlaces?: number): string;
|
|
37
|
+
/** 按常见表格数字 pattern 格式化自定义数字。 */
|
|
38
|
+
declare function formatCustomNumberPattern(value: unknown, pattern: string): string;
|
|
39
|
+
/** 将阿拉伯数字或中文数字转换为中文数字。 */
|
|
40
|
+
declare function formatChineseNumber(value: unknown, style?: ChineseNumberStyle): string | null;
|
|
41
|
+
/** 将普通中文数字或金融大写数字解析为阿拉伯数字。 */
|
|
42
|
+
declare function parseChineseNumber(value: unknown): number | null;
|
|
43
|
+
|
|
44
|
+
export { type ChineseNumberStyle, type NumberFormatOptions, type PreciseNumberInput, type PreciseRoundingMode, addPreciseNumbers, comparePreciseNumbers, dividePreciseNumber, formatChineseNumber, formatCustomNumberPattern, formatNumberValue, formatPercentValue, formatPreciseNumber, formatScientificValue, normalizeDecimalPlaces, parseChineseNumber, parseNumberValue, roundPreciseNumber, sumPreciseNumbers };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** 可参与精确十进制计算的值。字符串可保留超出 Number 安全范围的整数精度。 */
|
|
2
|
+
type PreciseNumberInput = string | number | bigint;
|
|
3
|
+
type PreciseRoundingMode = "round" | "floor" | "ceil" | "truncate";
|
|
4
|
+
/** 精确相加两个十进制数,非法或非有限输入返回 null。 */
|
|
5
|
+
declare function addPreciseNumbers(left: PreciseNumberInput, right: PreciseNumberInput): string | null;
|
|
6
|
+
/** 精确累加一组十进制数,非法值跳过且没有有效值时返回 null。 */
|
|
7
|
+
declare function sumPreciseNumbers(values: Iterable<PreciseNumberInput>): string | null;
|
|
8
|
+
/** 比较两个十进制数,返回 -1、0、1;非法输入返回 null。 */
|
|
9
|
+
declare function comparePreciseNumbers(left: PreciseNumberInput, right: PreciseNumberInput): -1 | 0 | 1 | null;
|
|
10
|
+
/** 精确除法并按指定小数位四舍五入。 */
|
|
11
|
+
declare function dividePreciseNumber(value: PreciseNumberInput, divisor: PreciseNumberInput, precision?: number): string | null;
|
|
12
|
+
/** 对十进制数进行四舍五入并保留指定小数位。 */
|
|
13
|
+
declare function roundPreciseNumber(value: PreciseNumberInput, precision: number, mode?: PreciseRoundingMode): string | null;
|
|
14
|
+
/** 格式化十进制数,可选择保留输入值的尾随零。 */
|
|
15
|
+
declare function formatPreciseNumber(value: PreciseNumberInput, precision?: number, preserveTrailingZeros?: boolean): string | null;
|
|
16
|
+
|
|
17
|
+
/** 通用数字格式化选项。 */
|
|
18
|
+
interface NumberFormatOptions {
|
|
19
|
+
/** 小数位数;`"auto"` 表示保留原始小数位。 */
|
|
20
|
+
decimalPlaces?: number | "auto";
|
|
21
|
+
/** 是否使用千分位分隔符,传入字符串时作为分隔符。 */
|
|
22
|
+
thousandsSeparator?: boolean | string;
|
|
23
|
+
/** 前置符号,例如 `¥` 或 `$`。 */
|
|
24
|
+
symbol?: string;
|
|
25
|
+
}
|
|
26
|
+
type ChineseNumberStyle = "common" | "financial";
|
|
27
|
+
/** 将数字、带千分位数字字符串解析为有限数字。 */
|
|
28
|
+
declare function parseNumberValue(value: unknown): number | null;
|
|
29
|
+
/** 限制小数位数到 0 到 20。 */
|
|
30
|
+
declare function normalizeDecimalPlaces(decimalPlaces: number | undefined, fallback?: number): number;
|
|
31
|
+
/** 格式化数字、金额和千分位数字。 */
|
|
32
|
+
declare function formatNumberValue(value: unknown, options?: NumberFormatOptions): string;
|
|
33
|
+
/** 格式化百分比数值,输入 `0.125` 输出 `12.5%`。 */
|
|
34
|
+
declare function formatPercentValue(value: unknown, decimalPlaces?: number): string;
|
|
35
|
+
/** 格式化科学计数法,指数固定补足三位。 */
|
|
36
|
+
declare function formatScientificValue(value: unknown, decimalPlaces?: number): string;
|
|
37
|
+
/** 按常见表格数字 pattern 格式化自定义数字。 */
|
|
38
|
+
declare function formatCustomNumberPattern(value: unknown, pattern: string): string;
|
|
39
|
+
/** 将阿拉伯数字或中文数字转换为中文数字。 */
|
|
40
|
+
declare function formatChineseNumber(value: unknown, style?: ChineseNumberStyle): string | null;
|
|
41
|
+
/** 将普通中文数字或金融大写数字解析为阿拉伯数字。 */
|
|
42
|
+
declare function parseChineseNumber(value: unknown): number | null;
|
|
43
|
+
|
|
44
|
+
export { type ChineseNumberStyle, type NumberFormatOptions, type PreciseNumberInput, type PreciseRoundingMode, addPreciseNumbers, comparePreciseNumbers, dividePreciseNumber, formatChineseNumber, formatCustomNumberPattern, formatNumberValue, formatPercentValue, formatPreciseNumber, formatScientificValue, normalizeDecimalPlaces, parseChineseNumber, parseNumberValue, roundPreciseNumber, sumPreciseNumbers };
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
// src/number/precise.ts
|
|
2
|
+
function addPreciseNumbers(left, right) {
|
|
3
|
+
const leftParts = parseDecimal(left);
|
|
4
|
+
const rightParts = parseDecimal(right);
|
|
5
|
+
if (!leftParts || !rightParts) return null;
|
|
6
|
+
return formatDecimal(addParts(leftParts, rightParts));
|
|
7
|
+
}
|
|
8
|
+
function sumPreciseNumbers(values) {
|
|
9
|
+
let result = { coefficient: 0n, scale: 0 };
|
|
10
|
+
let count = 0;
|
|
11
|
+
for (const value of values) {
|
|
12
|
+
const parts = parseDecimal(value);
|
|
13
|
+
if (!parts) continue;
|
|
14
|
+
result = addParts(result, parts);
|
|
15
|
+
count += 1;
|
|
16
|
+
}
|
|
17
|
+
return count === 0 ? null : formatDecimal(result);
|
|
18
|
+
}
|
|
19
|
+
function comparePreciseNumbers(left, right) {
|
|
20
|
+
const leftParts = parseDecimal(left);
|
|
21
|
+
const rightParts = parseDecimal(right);
|
|
22
|
+
if (!leftParts || !rightParts) return null;
|
|
23
|
+
const scale = Math.max(leftParts.scale, rightParts.scale);
|
|
24
|
+
const leftValue = leftParts.coefficient * 10n ** BigInt(scale - leftParts.scale);
|
|
25
|
+
const rightValue = rightParts.coefficient * 10n ** BigInt(scale - rightParts.scale);
|
|
26
|
+
return leftValue < rightValue ? -1 : leftValue > rightValue ? 1 : 0;
|
|
27
|
+
}
|
|
28
|
+
function dividePreciseNumber(value, divisor, precision = 20) {
|
|
29
|
+
const valueParts = parseDecimal(value);
|
|
30
|
+
const divisorParts = parseDecimal(divisor);
|
|
31
|
+
if (!valueParts || !divisorParts || divisorParts.coefficient === 0n)
|
|
32
|
+
return null;
|
|
33
|
+
const places = normalizePrecision(precision);
|
|
34
|
+
const scale = places + divisorParts.scale - valueParts.scale;
|
|
35
|
+
const factor = 10n ** BigInt(Math.max(scale, 0));
|
|
36
|
+
const numerator = valueParts.coefficient * factor;
|
|
37
|
+
const denominator = divisorParts.coefficient;
|
|
38
|
+
const quotient = numerator / denominator;
|
|
39
|
+
const remainder = numerator % denominator;
|
|
40
|
+
const rounded = remainder === 0n ? quotient : quotient + (numerator < 0n === denominator < 0n ? 1n : -1n) * (abs(remainder) * 2n >= abs(denominator) ? 1n : 0n);
|
|
41
|
+
return formatDecimal({ coefficient: rounded, scale: Math.max(places, 0) });
|
|
42
|
+
}
|
|
43
|
+
function roundPreciseNumber(value, precision, mode = "round") {
|
|
44
|
+
const parts = parseDecimal(value);
|
|
45
|
+
if (!parts) return null;
|
|
46
|
+
const places = normalizePrecision(precision);
|
|
47
|
+
if (parts.scale <= places)
|
|
48
|
+
return formatDecimal(
|
|
49
|
+
{
|
|
50
|
+
...parts,
|
|
51
|
+
coefficient: parts.coefficient * 10n ** BigInt(places - parts.scale)
|
|
52
|
+
},
|
|
53
|
+
places
|
|
54
|
+
);
|
|
55
|
+
const factor = 10n ** BigInt(parts.scale - places);
|
|
56
|
+
let quotient = parts.coefficient / factor;
|
|
57
|
+
const remainder = parts.coefficient % factor;
|
|
58
|
+
if (remainder !== 0n) {
|
|
59
|
+
const isNegative = parts.coefficient < 0n;
|
|
60
|
+
const direction = isNegative ? -1n : 1n;
|
|
61
|
+
if (mode === "ceil" && !isNegative || mode === "floor" && isNegative || mode === "round" && abs(remainder) * 2n >= factor) {
|
|
62
|
+
quotient += direction;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return formatDecimal({ coefficient: quotient, scale: places }, places);
|
|
66
|
+
}
|
|
67
|
+
function formatPreciseNumber(value, precision, preserveTrailingZeros = false) {
|
|
68
|
+
const parts = parseDecimal(value);
|
|
69
|
+
if (!parts) return null;
|
|
70
|
+
return precision == null ? formatDecimal(parts, preserveTrailingZeros ? parts.scale : 0) : roundPreciseNumber(value, precision);
|
|
71
|
+
}
|
|
72
|
+
function parseDecimal(value) {
|
|
73
|
+
if (typeof value === "number") {
|
|
74
|
+
if (!Number.isFinite(value)) return null;
|
|
75
|
+
value = String(value);
|
|
76
|
+
} else if (typeof value === "bigint") {
|
|
77
|
+
return { coefficient: value, scale: 0 };
|
|
78
|
+
}
|
|
79
|
+
const match = value.trim().match(/^([+-]?)(\d+)(?:\.(\d*))?(?:e([+-]?\d+))?$/i);
|
|
80
|
+
if (!match) return null;
|
|
81
|
+
const fraction = match[3] ?? "";
|
|
82
|
+
const exponent = Number(match[4] ?? 0);
|
|
83
|
+
if (!Number.isSafeInteger(exponent)) return null;
|
|
84
|
+
const scale = fraction.length - exponent;
|
|
85
|
+
const coefficient = BigInt(
|
|
86
|
+
`${match[1] === "-" ? "-" : ""}${match[2]}${fraction}`
|
|
87
|
+
);
|
|
88
|
+
return scale >= 0 ? { coefficient, scale } : { coefficient: coefficient * 10n ** BigInt(-scale), scale: 0 };
|
|
89
|
+
}
|
|
90
|
+
function addParts(left, right) {
|
|
91
|
+
const scale = Math.max(left.scale, right.scale);
|
|
92
|
+
return {
|
|
93
|
+
coefficient: left.coefficient * 10n ** BigInt(scale - left.scale) + right.coefficient * 10n ** BigInt(scale - right.scale),
|
|
94
|
+
scale
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function formatDecimal(parts, minimumScale = 0) {
|
|
98
|
+
const negative = parts.coefficient < 0n;
|
|
99
|
+
const digits = abs(parts.coefficient).toString().padStart(parts.scale + 1, "0");
|
|
100
|
+
const scale = Math.max(parts.scale, minimumScale);
|
|
101
|
+
const padded = digits.padStart(scale + 1, "0");
|
|
102
|
+
const integer = padded.slice(0, -scale || void 0) || "0";
|
|
103
|
+
const fraction = scale > 0 ? padded.slice(-scale).padEnd(scale, "0") : "";
|
|
104
|
+
const displayFraction = minimumScale > 0 ? fraction : fraction.replace(/0+$/, "");
|
|
105
|
+
return `${negative ? "-" : ""}${integer}${displayFraction ? `.${displayFraction}` : ""}`;
|
|
106
|
+
}
|
|
107
|
+
function normalizePrecision(value) {
|
|
108
|
+
return Math.min(
|
|
109
|
+
100,
|
|
110
|
+
Math.max(0, Math.trunc(Number.isFinite(value) ? value : 20))
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
function abs(value) {
|
|
114
|
+
return value < 0n ? -value : value;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/number/index.ts
|
|
118
|
+
var COMMON_CHINESE_DIGITS = [
|
|
119
|
+
"\u96F6",
|
|
120
|
+
"\u4E00",
|
|
121
|
+
"\u4E8C",
|
|
122
|
+
"\u4E09",
|
|
123
|
+
"\u56DB",
|
|
124
|
+
"\u4E94",
|
|
125
|
+
"\u516D",
|
|
126
|
+
"\u4E03",
|
|
127
|
+
"\u516B",
|
|
128
|
+
"\u4E5D"
|
|
129
|
+
];
|
|
130
|
+
var FINANCIAL_CHINESE_DIGITS = [
|
|
131
|
+
"\u96F6",
|
|
132
|
+
"\u58F9",
|
|
133
|
+
"\u8D30",
|
|
134
|
+
"\u53C1",
|
|
135
|
+
"\u8086",
|
|
136
|
+
"\u4F0D",
|
|
137
|
+
"\u9646",
|
|
138
|
+
"\u67D2",
|
|
139
|
+
"\u634C",
|
|
140
|
+
"\u7396"
|
|
141
|
+
];
|
|
142
|
+
var COMMON_SECTION_UNITS = ["", "\u5341", "\u767E", "\u5343"];
|
|
143
|
+
var FINANCIAL_SECTION_UNITS = ["", "\u62FE", "\u4F70", "\u4EDF"];
|
|
144
|
+
var LARGE_CHINESE_UNITS = ["", "\u4E07", "\u4EBF", "\u5146", "\u4EAC"];
|
|
145
|
+
var CHINESE_DIGIT_VALUES = {
|
|
146
|
+
\u96F6: 0,
|
|
147
|
+
"\u3007": 0,
|
|
148
|
+
\u4E00: 1,
|
|
149
|
+
\u58F9: 1,
|
|
150
|
+
\u4E8C: 2,
|
|
151
|
+
\u8D30: 2,
|
|
152
|
+
\u8CB3: 2,
|
|
153
|
+
\u4E24: 2,
|
|
154
|
+
\u5169: 2,
|
|
155
|
+
\u4E09: 3,
|
|
156
|
+
\u53C1: 3,
|
|
157
|
+
\u53C3: 3,
|
|
158
|
+
\u56DB: 4,
|
|
159
|
+
\u8086: 4,
|
|
160
|
+
\u4E94: 5,
|
|
161
|
+
\u4F0D: 5,
|
|
162
|
+
\u516D: 6,
|
|
163
|
+
\u9646: 6,
|
|
164
|
+
\u9678: 6,
|
|
165
|
+
\u4E03: 7,
|
|
166
|
+
\u67D2: 7,
|
|
167
|
+
\u516B: 8,
|
|
168
|
+
\u634C: 8,
|
|
169
|
+
\u4E5D: 9,
|
|
170
|
+
\u7396: 9
|
|
171
|
+
};
|
|
172
|
+
var CHINESE_SMALL_UNIT_VALUES = {
|
|
173
|
+
\u5341: 10,
|
|
174
|
+
\u62FE: 10,
|
|
175
|
+
\u767E: 100,
|
|
176
|
+
\u4F70: 100,
|
|
177
|
+
\u5343: 1e3,
|
|
178
|
+
\u4EDF: 1e3
|
|
179
|
+
};
|
|
180
|
+
var CHINESE_LARGE_UNIT_VALUES = {
|
|
181
|
+
\u4E07: 1e4,
|
|
182
|
+
\u842C: 1e4,
|
|
183
|
+
\u4EBF: 1e8,
|
|
184
|
+
\u5104: 1e8,
|
|
185
|
+
\u5146: 1e12
|
|
186
|
+
};
|
|
187
|
+
function parseNumberValue(value) {
|
|
188
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
189
|
+
if (typeof value !== "string") return null;
|
|
190
|
+
const normalized = value.trim().replace(/,/g, "");
|
|
191
|
+
if (!normalized) return null;
|
|
192
|
+
const numericValue = Number(normalized);
|
|
193
|
+
return Number.isFinite(numericValue) ? numericValue : null;
|
|
194
|
+
}
|
|
195
|
+
function normalizeDecimalPlaces(decimalPlaces, fallback = 2) {
|
|
196
|
+
if (typeof decimalPlaces !== "number" || !Number.isFinite(decimalPlaces)) {
|
|
197
|
+
return fallback;
|
|
198
|
+
}
|
|
199
|
+
return Math.min(20, Math.max(Math.trunc(decimalPlaces), 0));
|
|
200
|
+
}
|
|
201
|
+
function formatNumberValue(value, options = {}) {
|
|
202
|
+
if (value == null || value === "") return "";
|
|
203
|
+
const numericValue = parseNumberValue(value);
|
|
204
|
+
if (numericValue == null) return String(value);
|
|
205
|
+
const separator = resolveThousandsSeparator(options.thousandsSeparator);
|
|
206
|
+
const decimalPlaces = options.decimalPlaces === "auto" ? void 0 : normalizeDecimalPlaces(options.decimalPlaces);
|
|
207
|
+
const absoluteText = decimalPlaces == null ? String(Math.abs(numericValue)) : Math.abs(numericValue).toFixed(decimalPlaces);
|
|
208
|
+
const [integerText = "0", decimalText] = absoluteText.split(".");
|
|
209
|
+
const formattedInteger = separator ? integerText.replace(/\B(?=(\d{3})+(?!\d))/g, separator) : integerText;
|
|
210
|
+
const sign = numericValue < 0 ? "-" : "";
|
|
211
|
+
return `${sign}${options.symbol ?? ""}${formattedInteger}${decimalText ? `.${decimalText}` : ""}`;
|
|
212
|
+
}
|
|
213
|
+
function formatPercentValue(value, decimalPlaces = 2) {
|
|
214
|
+
const numericValue = parseNumberValue(value);
|
|
215
|
+
if (numericValue == null) return String(value ?? "");
|
|
216
|
+
return `${(numericValue * 100).toFixed(normalizeDecimalPlaces(decimalPlaces))}%`;
|
|
217
|
+
}
|
|
218
|
+
function formatScientificValue(value, decimalPlaces = 2) {
|
|
219
|
+
const numericValue = parseNumberValue(value);
|
|
220
|
+
if (numericValue == null) return String(value ?? "");
|
|
221
|
+
const [mantissa, exponentText] = numericValue.toExponential(normalizeDecimalPlaces(decimalPlaces)).split("e");
|
|
222
|
+
const exponent = Number(exponentText ?? 0);
|
|
223
|
+
return `${mantissa}E${exponent >= 0 ? "+" : "-"}${String(Math.abs(exponent)).padStart(3, "0")}`;
|
|
224
|
+
}
|
|
225
|
+
function formatCustomNumberPattern(value, pattern) {
|
|
226
|
+
if (pattern.includes("@") || pattern.includes("\u901A\u7528\u683C\u5F0F")) {
|
|
227
|
+
return String(value ?? "");
|
|
228
|
+
}
|
|
229
|
+
const literalOnly = pattern.match(/^"([^"]*)"$/);
|
|
230
|
+
if (literalOnly) return literalOnly[1] ?? "";
|
|
231
|
+
const numericValue = parseNumberValue(value);
|
|
232
|
+
if (numericValue == null) return String(value ?? "");
|
|
233
|
+
const percent = pattern.includes("%");
|
|
234
|
+
const tenThousands = pattern.includes("\u4E07");
|
|
235
|
+
const decimalPlaces = pattern.match(/\.(0+)/)?.[1]?.length ?? 0;
|
|
236
|
+
const scaled = numericValue * (percent ? 100 : 1) / (tenThousands ? 1e4 : 1);
|
|
237
|
+
const symbol = pattern.includes("\xA5") ? "\xA5" : pattern.includes("$") ? "$" : "";
|
|
238
|
+
if (/e\+/i.test(pattern)) return formatScientificValue(scaled, decimalPlaces);
|
|
239
|
+
const text = formatNumberValue(scaled, {
|
|
240
|
+
decimalPlaces,
|
|
241
|
+
thousandsSeparator: pattern.includes(",") && !tenThousands,
|
|
242
|
+
symbol
|
|
243
|
+
});
|
|
244
|
+
return `${text}${tenThousands ? "\u4E07" : ""}${percent ? "%" : ""}`;
|
|
245
|
+
}
|
|
246
|
+
function formatChineseNumber(value, style = "financial") {
|
|
247
|
+
const numericValue = parseNumberValue(value) ?? (typeof value === "string" ? parseChineseNumber(value) : null);
|
|
248
|
+
if (numericValue == null || !Number.isFinite(numericValue)) return null;
|
|
249
|
+
const negative = numericValue < 0;
|
|
250
|
+
const absoluteValue = Math.abs(numericValue);
|
|
251
|
+
const [integerText, decimalText = ""] = toPlainNumberText(absoluteValue).split(".");
|
|
252
|
+
const digits = style === "financial" ? FINANCIAL_CHINESE_DIGITS : COMMON_CHINESE_DIGITS;
|
|
253
|
+
const sectionUnits = style === "financial" ? FINANCIAL_SECTION_UNITS : COMMON_SECTION_UNITS;
|
|
254
|
+
const integerResult = formatChineseInteger(
|
|
255
|
+
integerText ?? "0",
|
|
256
|
+
digits,
|
|
257
|
+
sectionUnits
|
|
258
|
+
);
|
|
259
|
+
const decimalResult = decimalText ? `\u70B9${Array.from(decimalText, (digit) => digits[Number(digit)] ?? "").join("")}` : "";
|
|
260
|
+
return `${negative ? "\u8D1F" : ""}${integerResult}${decimalResult}`;
|
|
261
|
+
}
|
|
262
|
+
function parseChineseNumber(value) {
|
|
263
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
264
|
+
if (typeof value !== "string") return null;
|
|
265
|
+
let source = value.trim().replace(/[\s,,]/g, "");
|
|
266
|
+
if (!source) return null;
|
|
267
|
+
const negative = source.startsWith("\u8D1F") || source.startsWith("-");
|
|
268
|
+
if (negative) source = source.slice(1);
|
|
269
|
+
const [integerSource = "", decimalSource] = source.split(/[点\.]/, 2);
|
|
270
|
+
if (!integerSource) return null;
|
|
271
|
+
const integerValue = parseChineseInteger(integerSource);
|
|
272
|
+
if (integerValue == null) return null;
|
|
273
|
+
let decimalValue = 0;
|
|
274
|
+
if (decimalSource) {
|
|
275
|
+
let scale = 0.1;
|
|
276
|
+
for (const character of decimalSource) {
|
|
277
|
+
const digit = resolveChineseDigit(character);
|
|
278
|
+
if (digit == null) return null;
|
|
279
|
+
decimalValue += digit * scale;
|
|
280
|
+
scale /= 10;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
const result = integerValue + decimalValue;
|
|
284
|
+
return negative ? -result : result;
|
|
285
|
+
}
|
|
286
|
+
function formatChineseInteger(integerText, digits, sectionUnits) {
|
|
287
|
+
const normalized = integerText.replace(/^0+(?=\d)/, "");
|
|
288
|
+
if (normalized === "0") return digits[0] ?? "\u96F6";
|
|
289
|
+
const sections = [];
|
|
290
|
+
for (let end = normalized.length; end > 0; end -= 4) {
|
|
291
|
+
sections.push(Number(normalized.slice(Math.max(0, end - 4), end)));
|
|
292
|
+
}
|
|
293
|
+
let result = "";
|
|
294
|
+
let pendingZero = false;
|
|
295
|
+
for (let index = sections.length - 1; index >= 0; index -= 1) {
|
|
296
|
+
const section = sections[index] ?? 0;
|
|
297
|
+
if (section === 0) {
|
|
298
|
+
if (result) pendingZero = true;
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
if (result && (pendingZero || section < 1e3)) result += digits[0] ?? "\u96F6";
|
|
302
|
+
result += formatChineseSection(section, digits, sectionUnits);
|
|
303
|
+
result += LARGE_CHINESE_UNITS[index] ?? "";
|
|
304
|
+
pendingZero = false;
|
|
305
|
+
}
|
|
306
|
+
return digits === COMMON_CHINESE_DIGITS && result.startsWith("\u4E00\u5341") ? result.slice(1) : result;
|
|
307
|
+
}
|
|
308
|
+
function formatChineseSection(section, digits, sectionUnits) {
|
|
309
|
+
let result = "";
|
|
310
|
+
let pendingZero = false;
|
|
311
|
+
for (let position = 3; position >= 0; position -= 1) {
|
|
312
|
+
const unitValue = 10 ** position;
|
|
313
|
+
const digit = Math.floor(section / unitValue) % 10;
|
|
314
|
+
if (digit === 0) {
|
|
315
|
+
if (result && section % unitValue !== 0) pendingZero = true;
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
if (pendingZero) result += digits[0] ?? "\u96F6";
|
|
319
|
+
result += `${digits[digit] ?? ""}${sectionUnits[position] ?? ""}`;
|
|
320
|
+
pendingZero = false;
|
|
321
|
+
}
|
|
322
|
+
return result;
|
|
323
|
+
}
|
|
324
|
+
function parseChineseInteger(source) {
|
|
325
|
+
const hasUnit = Array.from(source).some(
|
|
326
|
+
(character) => character in CHINESE_SMALL_UNIT_VALUES || character in CHINESE_LARGE_UNIT_VALUES
|
|
327
|
+
);
|
|
328
|
+
if (!hasUnit) {
|
|
329
|
+
let text = "";
|
|
330
|
+
for (const character of source) {
|
|
331
|
+
const digit2 = resolveChineseDigit(character);
|
|
332
|
+
if (digit2 == null) return null;
|
|
333
|
+
text += String(digit2);
|
|
334
|
+
}
|
|
335
|
+
return text ? Number(text) : null;
|
|
336
|
+
}
|
|
337
|
+
let total = 0;
|
|
338
|
+
let section = 0;
|
|
339
|
+
let digit = null;
|
|
340
|
+
for (const character of source) {
|
|
341
|
+
const digitValue = resolveChineseDigit(character);
|
|
342
|
+
if (digitValue != null) {
|
|
343
|
+
digit = digitValue;
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
const smallUnit = CHINESE_SMALL_UNIT_VALUES[character];
|
|
347
|
+
if (smallUnit) {
|
|
348
|
+
section += (digit ?? 1) * smallUnit;
|
|
349
|
+
digit = null;
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
const largeUnit = CHINESE_LARGE_UNIT_VALUES[character];
|
|
353
|
+
if (largeUnit) {
|
|
354
|
+
section += digit ?? 0;
|
|
355
|
+
total += section * largeUnit;
|
|
356
|
+
section = 0;
|
|
357
|
+
digit = null;
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
return total + section + (digit ?? 0);
|
|
363
|
+
}
|
|
364
|
+
function resolveChineseDigit(character) {
|
|
365
|
+
if (/\d/.test(character)) return Number(character);
|
|
366
|
+
return CHINESE_DIGIT_VALUES[character] ?? null;
|
|
367
|
+
}
|
|
368
|
+
function toPlainNumberText(value) {
|
|
369
|
+
const source = String(value);
|
|
370
|
+
if (!/[eE]/.test(source)) return source;
|
|
371
|
+
return value.toLocaleString("en-US", {
|
|
372
|
+
useGrouping: false,
|
|
373
|
+
maximumFractionDigits: 20
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
function resolveThousandsSeparator(separator) {
|
|
377
|
+
if (separator == null || separator === false) return "";
|
|
378
|
+
if (typeof separator === "string") return separator;
|
|
379
|
+
return ",";
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
export { addPreciseNumbers, comparePreciseNumbers, dividePreciseNumber, formatChineseNumber, formatCustomNumberPattern, formatNumberValue, formatPercentValue, formatPreciseNumber, formatScientificValue, normalizeDecimalPlaces, parseChineseNumber, parseNumberValue, roundPreciseNumber, sumPreciseNumbers };
|
|
383
|
+
//# sourceMappingURL=index.js.map
|
|
384
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/number/precise.ts","../../src/number/index.ts"],"names":["digit"],"mappings":"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","file":"index.js","sourcesContent":["/** 可参与精确十进制计算的值。字符串可保留超出 Number 安全范围的整数精度。 */\r\nexport type PreciseNumberInput = string | number | bigint;\r\nexport type PreciseRoundingMode = \"round\" | \"floor\" | \"ceil\" | \"truncate\";\r\n\r\ninterface DecimalParts {\r\n coefficient: bigint;\r\n scale: number;\r\n}\r\n\r\n/** 精确相加两个十进制数,非法或非有限输入返回 null。 */\r\nexport function addPreciseNumbers(\r\n left: PreciseNumberInput,\r\n right: PreciseNumberInput,\r\n): string | null {\r\n const leftParts = parseDecimal(left);\r\n const rightParts = parseDecimal(right);\r\n if (!leftParts || !rightParts) return null;\r\n return formatDecimal(addParts(leftParts, rightParts));\r\n}\r\n\r\n/** 精确累加一组十进制数,非法值跳过且没有有效值时返回 null。 */\r\nexport function sumPreciseNumbers(\r\n values: Iterable<PreciseNumberInput>,\r\n): string | null {\r\n let result: DecimalParts = { coefficient: 0n, scale: 0 };\r\n let count = 0;\r\n for (const value of values) {\r\n const parts = parseDecimal(value);\r\n if (!parts) continue;\r\n result = addParts(result, parts);\r\n count += 1;\r\n }\r\n return count === 0 ? null : formatDecimal(result);\r\n}\r\n\r\n/** 比较两个十进制数,返回 -1、0、1;非法输入返回 null。 */\r\nexport function comparePreciseNumbers(\r\n left: PreciseNumberInput,\r\n right: PreciseNumberInput,\r\n): -1 | 0 | 1 | null {\r\n const leftParts = parseDecimal(left);\r\n const rightParts = parseDecimal(right);\r\n if (!leftParts || !rightParts) return null;\r\n const scale = Math.max(leftParts.scale, rightParts.scale);\r\n const leftValue =\r\n leftParts.coefficient * 10n ** BigInt(scale - leftParts.scale);\r\n const rightValue =\r\n rightParts.coefficient * 10n ** BigInt(scale - rightParts.scale);\r\n return leftValue < rightValue ? -1 : leftValue > rightValue ? 1 : 0;\r\n}\r\n\r\n/** 精确除法并按指定小数位四舍五入。 */\r\nexport function dividePreciseNumber(\r\n value: PreciseNumberInput,\r\n divisor: PreciseNumberInput,\r\n precision = 20,\r\n): string | null {\r\n const valueParts = parseDecimal(value);\r\n const divisorParts = parseDecimal(divisor);\r\n if (!valueParts || !divisorParts || divisorParts.coefficient === 0n)\r\n return null;\r\n const places = normalizePrecision(precision);\r\n const scale = places + divisorParts.scale - valueParts.scale;\r\n const factor = 10n ** BigInt(Math.max(scale, 0));\r\n const numerator = valueParts.coefficient * factor;\r\n const denominator = divisorParts.coefficient;\r\n const quotient = numerator / denominator;\r\n const remainder = numerator % denominator;\r\n const rounded =\r\n remainder === 0n\r\n ? quotient\r\n : quotient +\r\n (numerator < 0n === denominator < 0n ? 1n : -1n) *\r\n (abs(remainder) * 2n >= abs(denominator) ? 1n : 0n);\r\n return formatDecimal({ coefficient: rounded, scale: Math.max(places, 0) });\r\n}\r\n\r\n/** 对十进制数进行四舍五入并保留指定小数位。 */\r\nexport function roundPreciseNumber(\r\n value: PreciseNumberInput,\r\n precision: number,\r\n mode: PreciseRoundingMode = \"round\",\r\n): string | null {\r\n const parts = parseDecimal(value);\r\n if (!parts) return null;\r\n const places = normalizePrecision(precision);\r\n if (parts.scale <= places)\r\n return formatDecimal(\r\n {\r\n ...parts,\r\n coefficient: parts.coefficient * 10n ** BigInt(places - parts.scale),\r\n },\r\n places,\r\n );\r\n const factor = 10n ** BigInt(parts.scale - places);\r\n let quotient = parts.coefficient / factor;\r\n const remainder = parts.coefficient % factor;\r\n if (remainder !== 0n) {\r\n const isNegative = parts.coefficient < 0n;\r\n const direction = isNegative ? -1n : 1n;\r\n if (\r\n (mode === \"ceil\" && !isNegative) ||\r\n (mode === \"floor\" && isNegative) ||\r\n (mode === \"round\" && abs(remainder) * 2n >= factor)\r\n ) {\r\n quotient += direction;\r\n }\r\n }\r\n return formatDecimal({ coefficient: quotient, scale: places }, places);\r\n}\r\n\r\n/** 格式化十进制数,可选择保留输入值的尾随零。 */\r\nexport function formatPreciseNumber(\r\n value: PreciseNumberInput,\r\n precision?: number,\r\n preserveTrailingZeros = false,\r\n): string | null {\r\n const parts = parseDecimal(value);\r\n if (!parts) return null;\r\n return precision == null\r\n ? formatDecimal(parts, preserveTrailingZeros ? parts.scale : 0)\r\n : roundPreciseNumber(value, precision);\r\n}\r\n\r\nfunction parseDecimal(value: PreciseNumberInput): DecimalParts | null {\r\n if (typeof value === \"number\") {\r\n if (!Number.isFinite(value)) return null;\r\n value = String(value);\r\n } else if (typeof value === \"bigint\") {\r\n return { coefficient: value, scale: 0 };\r\n }\r\n const match = value\r\n .trim()\r\n .match(/^([+-]?)(\\d+)(?:\\.(\\d*))?(?:e([+-]?\\d+))?$/i);\r\n if (!match) return null;\r\n const fraction = match[3] ?? \"\";\r\n const exponent = Number(match[4] ?? 0);\r\n if (!Number.isSafeInteger(exponent)) return null;\r\n const scale = fraction.length - exponent;\r\n const coefficient = BigInt(\r\n `${match[1] === \"-\" ? \"-\" : \"\"}${match[2]}${fraction}`,\r\n );\r\n return scale >= 0\r\n ? { coefficient, scale }\r\n : { coefficient: coefficient * 10n ** BigInt(-scale), scale: 0 };\r\n}\r\n\r\nfunction addParts(left: DecimalParts, right: DecimalParts): DecimalParts {\r\n const scale = Math.max(left.scale, right.scale);\r\n return {\r\n coefficient:\r\n left.coefficient * 10n ** BigInt(scale - left.scale) +\r\n right.coefficient * 10n ** BigInt(scale - right.scale),\r\n scale,\r\n };\r\n}\r\n\r\nfunction formatDecimal(parts: DecimalParts, minimumScale = 0): string {\r\n const negative = parts.coefficient < 0n;\r\n const digits = abs(parts.coefficient)\r\n .toString()\r\n .padStart(parts.scale + 1, \"0\");\r\n const scale = Math.max(parts.scale, minimumScale);\r\n const padded = digits.padStart(scale + 1, \"0\");\r\n const integer = padded.slice(0, -scale || undefined) || \"0\";\r\n const fraction = scale > 0 ? padded.slice(-scale).padEnd(scale, \"0\") : \"\";\r\n const displayFraction =\r\n minimumScale > 0 ? fraction : fraction.replace(/0+$/, \"\");\r\n return `${negative ? \"-\" : \"\"}${integer}${displayFraction ? `.${displayFraction}` : \"\"}`;\r\n}\r\n\r\nfunction normalizePrecision(value: number) {\r\n return Math.min(\r\n 100,\r\n Math.max(0, Math.trunc(Number.isFinite(value) ? value : 20)),\r\n );\r\n}\r\n\r\nfunction abs(value: bigint) {\r\n return value < 0n ? -value : value;\r\n}\r\n","/** 通用数字格式化选项。 */\r\nexport interface NumberFormatOptions {\r\n /** 小数位数;`\"auto\"` 表示保留原始小数位。 */\r\n decimalPlaces?: number | \"auto\";\r\n /** 是否使用千分位分隔符,传入字符串时作为分隔符。 */\r\n thousandsSeparator?: boolean | string;\r\n /** 前置符号,例如 `¥` 或 `$`。 */\r\n symbol?: string;\r\n}\r\n\r\nexport type ChineseNumberStyle = \"common\" | \"financial\";\r\n\r\nconst COMMON_CHINESE_DIGITS = [\r\n \"零\",\r\n \"一\",\r\n \"二\",\r\n \"三\",\r\n \"四\",\r\n \"五\",\r\n \"六\",\r\n \"七\",\r\n \"八\",\r\n \"九\",\r\n];\r\nconst FINANCIAL_CHINESE_DIGITS = [\r\n \"零\",\r\n \"壹\",\r\n \"贰\",\r\n \"叁\",\r\n \"肆\",\r\n \"伍\",\r\n \"陆\",\r\n \"柒\",\r\n \"捌\",\r\n \"玖\",\r\n];\r\nconst COMMON_SECTION_UNITS = [\"\", \"十\", \"百\", \"千\"];\r\nconst FINANCIAL_SECTION_UNITS = [\"\", \"拾\", \"佰\", \"仟\"];\r\nconst LARGE_CHINESE_UNITS = [\"\", \"万\", \"亿\", \"兆\", \"京\"];\r\n\r\nconst CHINESE_DIGIT_VALUES: Record<string, number> = {\r\n 零: 0,\r\n 〇: 0,\r\n 一: 1,\r\n 壹: 1,\r\n 二: 2,\r\n 贰: 2,\r\n 貳: 2,\r\n 两: 2,\r\n 兩: 2,\r\n 三: 3,\r\n 叁: 3,\r\n 參: 3,\r\n 四: 4,\r\n 肆: 4,\r\n 五: 5,\r\n 伍: 5,\r\n 六: 6,\r\n 陆: 6,\r\n 陸: 6,\r\n 七: 7,\r\n 柒: 7,\r\n 八: 8,\r\n 捌: 8,\r\n 九: 9,\r\n 玖: 9,\r\n};\r\n\r\nconst CHINESE_SMALL_UNIT_VALUES: Record<string, number> = {\r\n 十: 10,\r\n 拾: 10,\r\n 百: 100,\r\n 佰: 100,\r\n 千: 1000,\r\n 仟: 1000,\r\n};\r\n\r\nconst CHINESE_LARGE_UNIT_VALUES: Record<string, number> = {\r\n 万: 10_000,\r\n 萬: 10_000,\r\n 亿: 100_000_000,\r\n 億: 100_000_000,\r\n 兆: 1_000_000_000_000,\r\n};\r\n\r\n/** 将数字、带千分位数字字符串解析为有限数字。 */\r\nexport function parseNumberValue(value: unknown): number | null {\r\n if (typeof value === \"number\") return Number.isFinite(value) ? value : null;\r\n if (typeof value !== \"string\") return null;\r\n const normalized = value.trim().replace(/,/g, \"\");\r\n if (!normalized) return null;\r\n const numericValue = Number(normalized);\r\n return Number.isFinite(numericValue) ? numericValue : null;\r\n}\r\n\r\n/** 限制小数位数到 0 到 20。 */\r\nexport function normalizeDecimalPlaces(\r\n decimalPlaces: number | undefined,\r\n fallback = 2,\r\n) {\r\n if (typeof decimalPlaces !== \"number\" || !Number.isFinite(decimalPlaces)) {\r\n return fallback;\r\n }\r\n return Math.min(20, Math.max(Math.trunc(decimalPlaces), 0));\r\n}\r\n\r\n/** 格式化数字、金额和千分位数字。 */\r\nexport function formatNumberValue(\r\n value: unknown,\r\n options: NumberFormatOptions = {},\r\n) {\r\n if (value == null || value === \"\") return \"\";\r\n const numericValue = parseNumberValue(value);\r\n if (numericValue == null) return String(value);\r\n const separator = resolveThousandsSeparator(options.thousandsSeparator);\r\n const decimalPlaces =\r\n options.decimalPlaces === \"auto\"\r\n ? undefined\r\n : normalizeDecimalPlaces(options.decimalPlaces);\r\n const absoluteText =\r\n decimalPlaces == null\r\n ? String(Math.abs(numericValue))\r\n : Math.abs(numericValue).toFixed(decimalPlaces);\r\n const [integerText = \"0\", decimalText] = absoluteText.split(\".\");\r\n const formattedInteger = separator\r\n ? integerText.replace(/\\B(?=(\\d{3})+(?!\\d))/g, separator)\r\n : integerText;\r\n const sign = numericValue < 0 ? \"-\" : \"\";\r\n return `${sign}${options.symbol ?? \"\"}${formattedInteger}${decimalText ? `.${decimalText}` : \"\"}`;\r\n}\r\n\r\n/** 格式化百分比数值,输入 `0.125` 输出 `12.5%`。 */\r\nexport function formatPercentValue(value: unknown, decimalPlaces = 2) {\r\n const numericValue = parseNumberValue(value);\r\n if (numericValue == null) return String(value ?? \"\");\r\n return `${(numericValue * 100).toFixed(normalizeDecimalPlaces(decimalPlaces))}%`;\r\n}\r\n\r\n/** 格式化科学计数法,指数固定补足三位。 */\r\nexport function formatScientificValue(value: unknown, decimalPlaces = 2) {\r\n const numericValue = parseNumberValue(value);\r\n if (numericValue == null) return String(value ?? \"\");\r\n const [mantissa, exponentText] = numericValue\r\n .toExponential(normalizeDecimalPlaces(decimalPlaces))\r\n .split(\"e\");\r\n const exponent = Number(exponentText ?? 0);\r\n return `${mantissa}E${exponent >= 0 ? \"+\" : \"-\"}${String(Math.abs(exponent)).padStart(3, \"0\")}`;\r\n}\r\n\r\n/** 按常见表格数字 pattern 格式化自定义数字。 */\r\nexport function formatCustomNumberPattern(value: unknown, pattern: string) {\r\n if (pattern.includes(\"@\") || pattern.includes(\"通用格式\")) {\r\n return String(value ?? \"\");\r\n }\r\n const literalOnly = pattern.match(/^\"([^\"]*)\"$/);\r\n if (literalOnly) return literalOnly[1] ?? \"\";\r\n const numericValue = parseNumberValue(value);\r\n if (numericValue == null) return String(value ?? \"\");\r\n const percent = pattern.includes(\"%\");\r\n const tenThousands = pattern.includes(\"万\");\r\n const decimalPlaces = pattern.match(/\\.(0+)/)?.[1]?.length ?? 0;\r\n const scaled =\r\n (numericValue * (percent ? 100 : 1)) / (tenThousands ? 10_000 : 1);\r\n const symbol = pattern.includes(\"¥\") ? \"¥\" : pattern.includes(\"$\") ? \"$\" : \"\";\r\n if (/e\\+/i.test(pattern)) return formatScientificValue(scaled, decimalPlaces);\r\n const text = formatNumberValue(scaled, {\r\n decimalPlaces,\r\n thousandsSeparator: pattern.includes(\",\") && !tenThousands,\r\n symbol,\r\n });\r\n return `${text}${tenThousands ? \"万\" : \"\"}${percent ? \"%\" : \"\"}`;\r\n}\r\n\r\n/** 将阿拉伯数字或中文数字转换为中文数字。 */\r\nexport function formatChineseNumber(\r\n value: unknown,\r\n style: ChineseNumberStyle = \"financial\",\r\n): string | null {\r\n const numericValue =\r\n parseNumberValue(value) ??\r\n (typeof value === \"string\" ? parseChineseNumber(value) : null);\r\n if (numericValue == null || !Number.isFinite(numericValue)) return null;\r\n const negative = numericValue < 0;\r\n const absoluteValue = Math.abs(numericValue);\r\n const [integerText, decimalText = \"\"] =\r\n toPlainNumberText(absoluteValue).split(\".\");\r\n const digits =\r\n style === \"financial\" ? FINANCIAL_CHINESE_DIGITS : COMMON_CHINESE_DIGITS;\r\n const sectionUnits =\r\n style === \"financial\" ? FINANCIAL_SECTION_UNITS : COMMON_SECTION_UNITS;\r\n const integerResult = formatChineseInteger(\r\n integerText ?? \"0\",\r\n digits,\r\n sectionUnits,\r\n );\r\n const decimalResult = decimalText\r\n ? `点${Array.from(decimalText, (digit) => digits[Number(digit)] ?? \"\").join(\"\")}`\r\n : \"\";\r\n return `${negative ? \"负\" : \"\"}${integerResult}${decimalResult}`;\r\n}\r\n\r\n/** 将普通中文数字或金融大写数字解析为阿拉伯数字。 */\r\nexport function parseChineseNumber(value: unknown): number | null {\r\n if (typeof value === \"number\") return Number.isFinite(value) ? value : null;\r\n if (typeof value !== \"string\") return null;\r\n let source = value.trim().replace(/[\\s,,]/g, \"\");\r\n if (!source) return null;\r\n const negative = source.startsWith(\"负\") || source.startsWith(\"-\");\r\n if (negative) source = source.slice(1);\r\n const [integerSource = \"\", decimalSource] = source.split(/[点\\.]/, 2);\r\n if (!integerSource) return null;\r\n const integerValue = parseChineseInteger(integerSource);\r\n if (integerValue == null) return null;\r\n let decimalValue = 0;\r\n if (decimalSource) {\r\n let scale = 0.1;\r\n for (const character of decimalSource) {\r\n const digit = resolveChineseDigit(character);\r\n if (digit == null) return null;\r\n decimalValue += digit * scale;\r\n scale /= 10;\r\n }\r\n }\r\n const result = integerValue + decimalValue;\r\n return negative ? -result : result;\r\n}\r\n\r\nfunction formatChineseInteger(\r\n integerText: string,\r\n digits: string[],\r\n sectionUnits: string[],\r\n) {\r\n const normalized = integerText.replace(/^0+(?=\\d)/, \"\");\r\n if (normalized === \"0\") return digits[0] ?? \"零\";\r\n const sections: number[] = [];\r\n for (let end = normalized.length; end > 0; end -= 4) {\r\n sections.push(Number(normalized.slice(Math.max(0, end - 4), end)));\r\n }\r\n let result = \"\";\r\n let pendingZero = false;\r\n for (let index = sections.length - 1; index >= 0; index -= 1) {\r\n const section = sections[index] ?? 0;\r\n if (section === 0) {\r\n if (result) pendingZero = true;\r\n continue;\r\n }\r\n if (result && (pendingZero || section < 1000)) result += digits[0] ?? \"零\";\r\n result += formatChineseSection(section, digits, sectionUnits);\r\n result += LARGE_CHINESE_UNITS[index] ?? \"\";\r\n pendingZero = false;\r\n }\r\n return digits === COMMON_CHINESE_DIGITS && result.startsWith(\"一十\")\r\n ? result.slice(1)\r\n : result;\r\n}\r\n\r\nfunction formatChineseSection(\r\n section: number,\r\n digits: string[],\r\n sectionUnits: string[],\r\n) {\r\n let result = \"\";\r\n let pendingZero = false;\r\n for (let position = 3; position >= 0; position -= 1) {\r\n const unitValue = 10 ** position;\r\n const digit = Math.floor(section / unitValue) % 10;\r\n if (digit === 0) {\r\n if (result && section % unitValue !== 0) pendingZero = true;\r\n continue;\r\n }\r\n if (pendingZero) result += digits[0] ?? \"零\";\r\n result += `${digits[digit] ?? \"\"}${sectionUnits[position] ?? \"\"}`;\r\n pendingZero = false;\r\n }\r\n return result;\r\n}\r\n\r\nfunction parseChineseInteger(source: string) {\r\n const hasUnit = Array.from(source).some(\r\n (character) =>\r\n character in CHINESE_SMALL_UNIT_VALUES ||\r\n character in CHINESE_LARGE_UNIT_VALUES,\r\n );\r\n if (!hasUnit) {\r\n let text = \"\";\r\n for (const character of source) {\r\n const digit = resolveChineseDigit(character);\r\n if (digit == null) return null;\r\n text += String(digit);\r\n }\r\n return text ? Number(text) : null;\r\n }\r\n let total = 0;\r\n let section = 0;\r\n let digit: number | null = null;\r\n for (const character of source) {\r\n const digitValue = resolveChineseDigit(character);\r\n if (digitValue != null) {\r\n digit = digitValue;\r\n continue;\r\n }\r\n const smallUnit = CHINESE_SMALL_UNIT_VALUES[character];\r\n if (smallUnit) {\r\n section += (digit ?? 1) * smallUnit;\r\n digit = null;\r\n continue;\r\n }\r\n const largeUnit = CHINESE_LARGE_UNIT_VALUES[character];\r\n if (largeUnit) {\r\n section += digit ?? 0;\r\n total += section * largeUnit;\r\n section = 0;\r\n digit = null;\r\n continue;\r\n }\r\n return null;\r\n }\r\n return total + section + (digit ?? 0);\r\n}\r\n\r\nfunction resolveChineseDigit(character: string) {\r\n if (/\\d/.test(character)) return Number(character);\r\n return CHINESE_DIGIT_VALUES[character] ?? null;\r\n}\r\n\r\nfunction toPlainNumberText(value: number) {\r\n const source = String(value);\r\n if (!/[eE]/.test(source)) return source;\r\n return value.toLocaleString(\"en-US\", {\r\n useGrouping: false,\r\n maximumFractionDigits: 20,\r\n });\r\n}\r\n\r\nfunction resolveThousandsSeparator(separator: boolean | string | undefined) {\r\n if (separator == null || separator === false) return \"\";\r\n if (typeof separator === \"string\") return separator;\r\n return \",\";\r\n}\r\nexport {\r\n addPreciseNumbers,\r\n comparePreciseNumbers,\r\n dividePreciseNumber,\r\n formatPreciseNumber,\r\n roundPreciseNumber,\r\n sumPreciseNumbers,\r\n} from \"./precise\";\r\nexport type { PreciseNumberInput } from \"./precise\";\r\nexport type { PreciseRoundingMode } from \"./precise\";\r\n"]}
|