cjk-number 0.3.0 → 0.4.1

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
@@ -26,7 +26,7 @@ npm install cjk-number
26
26
 
27
27
  ```js
28
28
  import {
29
- integer,
29
+ number,
30
30
  cjkIdeographic,
31
31
  tradChineseInformal,
32
32
  tradChineseFormal,
@@ -39,20 +39,31 @@ import {
39
39
  hiragana
40
40
  } from "cjk-number";
41
41
 
42
- // parse string -> number/bigint
42
+ // parse string -> number / bigint / string
43
43
  number.parse("一千零二十三"); // 1023
44
44
  number.parse("壹仟零貳拾參"); // 1023
45
45
  number.parse("負一百零二"); // -102
46
46
  number.parse("一點二三"); // 1.23
47
- number.parse("一無量大數", { preferBigInt: true }); // 10n ** 68n
47
+ number.parse("一無量大數", { mode: "preferBigInt" }); // 10n ** 68n
48
+ number.parse("一京點一", { mode: "exactDecimal" }); // "10000000000000000.1" (lossless)
48
49
 
49
- // format number/bigint -> string
50
+ // format number/bigint/string -> CJK
50
51
  cjkIdeographic.parse(1023); // "一千零二十三"
51
52
  tradChineseFormal.parse(1023); // "壹仟零貳拾參"
52
53
  simpChineseFormal.parse(1023); // "壹仟零贰拾叁"
53
54
  koreanHangulFormal.parse(10n ** 68n); // "일무량대수"
54
55
  japaneseFormal.parse(10n ** 68n); // "壱無量大数"
55
56
 
57
+ // arithmetic on CJK strings (exact BigFloat engine)
58
+ tradChineseInformal.add(["一兆", "一點五"]); // "一兆零一點五"
59
+ tradChineseInformal.subtract(["一京", "一兆"]); // "九千九百九十九兆"
60
+ tradChineseInformal.multiply(["一億", "一億"]); // "一京"
61
+ tradChineseInformal.divide(["五", "二"]); // "二點五"
62
+ tradChineseInformal.modulo("五", "二"); // "一"
63
+ tradChineseInformal.pow("二", "十"); // "一千零二十四"
64
+ tradChineseInformal.abs("負一兆"); // "一兆"
65
+ ["三十", "二", "十一"].sort(tradChineseInformal.compare); // ["二", "十一", "三十"]
66
+
56
67
  // stem/branch
57
68
  cjkHeavenlyStem.parse(10); // "癸"
58
69
  cjkEarthlyBranch.parse(12); // "亥"
@@ -66,35 +77,67 @@ hiragana.parse(46); // "ん"
66
77
 
67
78
  ### number.parse(input, options?)
68
79
 
69
- Parses CJK text into number or bigint.
80
+ Parses CJK text into a `number`, `bigint`, or exact decimal `string`.
70
81
 
71
82
  Options:
72
83
 
73
- - strict?: boolean
74
- - preferBigInt?: boolean
75
- - heavenlyStemMode?: "fixed" | "cyclic"
76
- - earthlyBranchMode?: "fixed" | "cyclic"
84
+ | Option | Type | Default | Description |
85
+ |---|---|---|---|
86
+ | `mode` | `"number" \| "preferBigInt" \| "exactDecimal"` | `"number"` | Controls the output numeric type |
87
+ | `strict` | `boolean` | `false` | Rejects unsupported characters early |
88
+ | `heavenlyStemMode` | `"fixed" \| "cyclic"` | `"fixed"` | How to handle out-of-range stem values |
89
+ | `earthlyBranchMode` | `"fixed" \| "cyclic"` | `"fixed"` | How to handle out-of-range branch values |
90
+ | `explicitTyping` | `ExplicitTyping` | `undefined` | Forces a specific CJK system for parsing |
91
+
92
+ **`mode` values:**
93
+
94
+ - `"number"` (default) — returns `number`; auto-promotes to `bigint` if the integer exceeds `Number.MAX_SAFE_INTEGER`.
95
+ - `"preferBigInt"` — always returns `bigint` for integer parse paths.
96
+ - `"exactDecimal"` — returns a lossless decimal `string` (e.g. `"10000000000000000.1"`), bypassing the `MAX_SAFE_INTEGER` restriction for mixed large+decimal values.
77
97
 
78
- Behavior summary:
98
+ **`explicitTyping` values:**
79
99
 
80
- - If the value fits safely, returns number by default.
81
- - If out of Number safe range, returns bigint automatically.
82
- - If preferBigInt is true, always returns bigint for integer parse paths.
83
- - Decimal parse returns number.
100
+ - Choose from any of the available system names (e.g., `"hiraganaIroha"`, `"tradChineseFormal"`, `"koreanHangulFormal"`) to force the parser to use that system's mapping specifically. This is useful for resolving conflicts between systems that share the same symbols (like Hiragana Gojuon vs Iroha).
84
101
 
85
102
  Examples:
86
103
 
87
104
  ```js
88
- number.parse("九千零七兆一", { preferBigInt: true }); // 9007000000000001n
105
+ number.parse("九千零七兆一", { mode: "preferBigInt" }); // 9007000000000001n
89
106
  number.parse("癸"); // 10
90
107
  number.parse("亥"); // 12
91
- number.parse("壱京", { preferBigInt: true }); // 10n ** 16n
92
- number.parse("ぬ"); // 10 (iroha sequence symbol)
108
+ number.parse("壱京", { mode: "preferBigInt" }); // 10n ** 16n
109
+ number.parse("ぬ", { explicitTyping: "hiraganaIroha" }); // 10
110
+ number.parse("ぬ"); // 23 (default gojuon sequence)
111
+ number.parse("一京點一", { mode: "exactDecimal" }); // "10000000000000000.1"
93
112
  ```
94
113
 
95
114
  ### Formatters
96
115
 
97
- All formatters expose parse(value).
116
+ All formatters expose the following methods:
117
+
118
+ #### `parse(value)`
119
+
120
+ Formats a `number`, `bigint`, or exact decimal `string` into a CJK numeral string.
121
+
122
+ #### Arithmetic methods
123
+
124
+ All numeric formatters (not cyclic/sequence ones) also expose arithmetic methods that accept CJK strings and return a CJK string in the same numeral system:
125
+
126
+ ```js
127
+ tradChineseInformal.add(["一千", "二十三"]); // "一千零二十三"
128
+ tradChineseInformal.subtract(["一京", "一兆"]); // "九千九百九十九兆"
129
+ tradChineseInformal.multiply(["一億", "一億"]); // "一京"
130
+ tradChineseInformal.divide(["五", "二"]); // "二點五"
131
+ tradChineseInformal.modulo("五", "二"); // "一"
132
+ tradChineseInformal.pow("二", "三"); // "八"
133
+ tradChineseInformal.pow("二", 3); // "八" (exponent can be a number)
134
+ tradChineseInformal.abs("負五十"); // "五十"
135
+ tradChineseInformal.compare("三十", "二"); // 1
136
+ ["三十", "二", "十一"].sort(tradChineseInformal.compare); // ["二", "十一", "三十"]
137
+ ```
138
+
139
+ All arithmetic uses a **zero-dependency BigFloat engine**: decimal points are scaled out to `BigInt` before any operation, so results like `"一兆" + "一點五"` are exact with no floating-point drift.
140
+
98
141
 
99
142
  Available formatters:
100
143
 
@@ -115,11 +158,31 @@ Available formatters:
115
158
  - katakana
116
159
  - katakanaIroha
117
160
 
161
+ #### Sequence system methods
162
+
163
+ All sequence systems (stems, branches, and kana) also expose methods for traversing and decoding the sequence:
164
+
165
+ - `decode(symbol)`: Returns the 1-indexed numeric value of a symbol in the specific sequence.
166
+ - `next(symbol, count?)`: Returns the next symbol in the sequence (cyclic).
167
+ - `prev(symbol, count?)`: Returns the previous symbol in the sequence (cyclic).
168
+ - `range(start, end)`: Returns an array of symbols from `start` to `end` (inclusive).
169
+
170
+ Example:
171
+
172
+ ```js
173
+ hiraganaIroha.decode("ぬ"); // 10
174
+ hiragana.decode("ぬ"); // 23 (gojuon)
175
+
176
+ cjkHeavenlyStem.next("癸"); // "甲"
177
+ cjkEarthlyBranch.prev("子", 2); // "戌"
178
+ hiraganaIroha.range("ゑ", "す"); // ["ゑ", "ひ", "も", "せ", "す"]
179
+ ```
180
+
118
181
  Examples:
119
182
 
120
183
  ```js
121
184
  tradChineseInformal.parse(-320); // "負三百二十"
122
- simpChineseInformal.parse(12.34); // "十二點三四"
185
+ simpChineseInformal.parse(12.34); // "十二点三四"
123
186
  tradChineseFormal.parse(10n ** 68n); // "壹無量大數"
124
187
  simpChineseFormal.parse(10n ** 64n); // "壹不可思议"
125
188
 
@@ -197,10 +260,11 @@ number.parse("abc", { strict: true }); // throws SyntaxError
197
260
 
198
261
  Common thrown errors:
199
262
 
200
- - SyntaxError: unsupported/invalid text shape
201
- - RangeError: invalid formatter range in fixed sequence mode
202
- - RangeError: non-integer passed to integer-only paths
203
- - RangeError: decimal parse integer part exceeds Number.MAX_SAFE_INTEGER
263
+ - `SyntaxError`: unsupported or invalid text shape
264
+ - `RangeError`: invalid formatter range in fixed sequence mode
265
+ - `RangeError`: non-integer passed to integer-only paths
266
+ - `RangeError`: decimal parse integer part exceeds `Number.MAX_SAFE_INTEGER` — use `{ mode: "exactDecimal" }` to bypass
267
+ - `RangeError`: division by zero in `divide` or `modulo`
204
268
 
205
269
  ## Development
206
270
 
@@ -1,22 +1,26 @@
1
- import { DigitSet } from "./types.js";
2
- export declare const STEMS: readonly ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"];
3
- export declare const BRANCHES: readonly ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"];
4
- export declare const KOREAN_HANGUL_DIGITS: readonly ["일", "이", "삼", "사", "오", "육", "칠", "팔", "구"];
5
- export declare const KOREAN_HANJA_FORMAL_DIGITS: readonly ["壹", "貳", "參", "四", "五", "六", "七", "八", "九"];
6
- export declare const KOREAN_HANJA_INFORMAL_DIGITS: readonly ["一", "二", "三", "四", "五", "六", "七", "八", "九"];
7
- export declare const JAPANESE_FORMAL_DIGITS: readonly ["壱", "弐", "参", "四", "五", "六", "七", "八", "九"];
8
- export declare const JAPANESE_INFORMAL_DIGITS: readonly ["一", "二", "三", "四", "五", "六", "七", "八", "九"];
9
- export declare const HIRAGANA: readonly ["あ", "い", "う", "え", "お", "か", "き", "く", "け", "こ", "さ", "し", "す", "せ", "そ", "た", "ち", "つ", "て", "と", "な", "に", "ぬ", "ね", "の", "は", "ひ", "ふ", "へ", "ほ", "ま", "み", "む", "め", "も", "や", "ゆ", "よ", "ら", "り", "る", "れ", "ろ", "わ", "を", "ん"];
10
- export declare const HIRAGANA_IROHA: readonly ["い", "ろ", "は", "に", "ほ", "へ", "と", "ち", "り", "ぬ", "る", "を", "わ", "か", "よ", "た", "れ", "そ", "つ", "ね", "な", "ら", "む", "う", "ゐ", "の", "お", "く", "や", "ま", "け", "ふ", "こ", "え", "て", "あ", "さ", "き", "ゆ", "め", "み", "し", "ゑ", "ひ", "も", "せ", "す"];
11
- export declare const KATAKANA: readonly ["ア", "イ", "ウ", "エ", "オ", "カ", "キ", "ク", "ケ", "コ", "サ", "シ", "ス", "セ", "ソ", "タ", "チ", "ツ", "テ", "ト", "ナ", "ニ", "ヌ", "ネ", "ノ", "ハ", "ヒ", "フ", "ヘ", "ホ", "マ", "ミ", "ム", "メ", "モ", "ヤ", "ユ", "ヨ", "ラ", "リ", "ル", "レ", "ロ", "ワ", "ヲ", "ン"];
12
- export declare const KATAKANA_IROHA: readonly ["イ", "ロ", "ハ", "ニ", "ホ", "ヘ", "ト", "チ", "リ", "ヌ", "ル", "ヲ", "ワ", "カ", "ヨ", "タ", "レ", "ソ", "ツ", "ネ", "ナ", "ラ", "ム", "ウ", "ヰ", "ノ", "オ", "ク", "ヤ", "マ", "ケ", "フ", "コ", "エ", "テ", "ア", "サ", "キ", "ユ", "メ", "ミ", "シ", "ヱ", "ヒ", "モ", "セ", "ス"];
13
- export declare const KOREAN_BIG_UNITS: readonly ["만", "억", "조", "경", "해", "자", "양", "구", "간", "정", "재", "극", "항하사", "아승기", "나유타", "불가사의", "무량대수"];
14
- export declare const JAPANESE_BIG_UNITS: readonly ["万", "億", "兆", "京", "垓", "秭", "穣", "溝", "澗", "正", "載", "極", "恒河沙", "阿僧祇", "那由他", "不可思議", "無量大数"];
15
- export declare const SEQUENCE_SYMBOL_TO_NUMBER: Record<string, number>;
1
+ import { DigitArray9, DigitSet } from "./types.js";
2
+ export declare const TRAD_INFORMAL_DIGITS: DigitArray9;
3
+ export declare const SIMP_INFORMAL_DIGITS: DigitArray9;
4
+ export declare const TRAD_FORMAL_DIGITS: DigitArray9;
5
+ export declare const SIMP_FORMAL_DIGITS: DigitArray9;
6
+ export declare const KOREAN_HANGUL_DIGITS: DigitArray9;
7
+ export declare const KOREAN_HANJA_FORMAL_DIGITS: DigitArray9;
8
+ export declare const KOREAN_HANJA_INFORMAL_DIGITS: DigitArray9;
9
+ export declare const JAPANESE_FORMAL_DIGITS: DigitArray9;
10
+ export declare const JAPANESE_INFORMAL_DIGITS: DigitArray9;
11
+ export declare const STEMS: string[];
12
+ export declare const BRANCHES: string[];
13
+ export declare const HIRAGANA: string[];
14
+ export declare const HIRAGANA_IROHA: string[];
15
+ export declare const KATAKANA: string[];
16
+ export declare const KATAKANA_IROHA: string[];
17
+ export declare const KOREAN_BIG_UNITS: string[];
18
+ export declare const JAPANESE_BIG_UNITS: string[];
19
+ export declare const TRAD_BIG_UNITS: string[];
20
+ export declare const SIMP_BIG_UNITS: string[];
21
+ export declare function getSequenceMap(): Record<string, number>;
16
22
  export declare const CANONICAL_DIGITS: Record<string, number>;
17
23
  export declare const SMALL_UNITS: Record<string, bigint>;
18
- export declare const TRAD_BIG_UNITS: readonly ["萬", "億", "兆", "京", "垓", "秭", "穰", "溝", "澗", "正", "載", "極", "恆河沙", "阿僧祇", "那由他", "不可思議", "無量大數"];
19
- export declare const SIMP_BIG_UNITS: readonly ["万", "亿", "兆", "京", "垓", "秭", "穰", "沟", "涧", "正", "载", "极", "恒河沙", "阿僧祇", "那由他", "不可思议", "无量大数"];
20
24
  export declare const TRAD_INFORMAL_SET: DigitSet;
21
25
  export declare const TRAD_FORMAL_SET: DigitSet;
22
26
  export declare const SIMP_INFORMAL_SET: DigitSet;
@@ -27,4 +31,8 @@ export declare const KOREAN_HANJA_INFORMAL_SET: DigitSet;
27
31
  export declare const JAPANESE_FORMAL_SET: DigitSet;
28
32
  export declare const JAPANESE_INFORMAL_SET: DigitSet;
29
33
  export declare const BIG_UNIT_ORDER: [string, bigint][];
34
+ export interface ScaledValue {
35
+ big: bigint;
36
+ scale: number;
37
+ }
30
38
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,eAAO,MAAM,KAAK,6DAWR,CAAC;AACX,eAAO,MAAM,QAAQ,uEAaX,CAAC;AACX,eAAO,MAAM,oBAAoB,wDAUvB,CAAC;AACX,eAAO,MAAM,0BAA0B,wDAU7B,CAAC;AACX,eAAO,MAAM,4BAA4B,wDAU/B,CAAC;AACX,eAAO,MAAM,sBAAsB,wDAUzB,CAAC;AACX,eAAO,MAAM,wBAAwB,wDAU3B,CAAC;AACX,eAAO,MAAM,QAAQ,iPA+CX,CAAC;AACX,eAAO,MAAM,cAAc,sPAgDjB,CAAC;AACX,eAAO,MAAM,QAAQ,iPA+CX,CAAC;AACX,eAAO,MAAM,cAAc,sPAgDjB,CAAC;AAEX,eAAO,MAAM,gBAAgB,4GAkBnB,CAAC;AAEX,eAAO,MAAM,kBAAkB,4GAkBrB,CAAC;AAEX,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAgBzD,CAAC;AAEL,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA6BnD,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAO9C,CAAC;AAEF,eAAO,MAAM,cAAc,4GAkBjB,CAAC;AAEX,eAAO,MAAM,cAAc,4GAkBjB,CAAC;AAWX,eAAO,MAAM,iBAAiB,EAAE,QAM/B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,QAM7B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,QAM/B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,QAM7B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,QAM/B,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,QAMrC,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,QAMvC,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,QAMjC,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,QAMnC,CAAC;AAEF,eAAO,MAAM,cAAc,oBAAqC,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AASnD,eAAO,MAAM,oBAAoB,aAA6B,CAAC;AAC/D,eAAO,MAAM,oBAAoB,aAA6B,CAAC;AAC/D,eAAO,MAAM,kBAAkB,aAA6B,CAAC;AAC7D,eAAO,MAAM,kBAAkB,aAA6B,CAAC;AAC7D,eAAO,MAAM,oBAAoB,aAA6B,CAAC;AAC/D,eAAO,MAAM,0BAA0B,aAA6B,CAAC;AACrE,eAAO,MAAM,4BAA4B,aAA6B,CAAC;AACvE,eAAO,MAAM,sBAAsB,aAA6B,CAAC;AACjE,eAAO,MAAM,wBAAwB,aAA6B,CAAC;AAEnE,eAAO,MAAM,KAAK,UAA2B,CAAC;AAC9C,eAAO,MAAM,QAAQ,UAA6B,CAAC;AACnD,eAAO,MAAM,QAAQ,UAA6D,CAAC;AACnF,eAAO,MAAM,cAAc,UAA8D,CAAC;AAC1F,eAAO,MAAM,QAAQ,UAA6D,CAAC;AACnF,eAAO,MAAM,cAAc,UAA8D,CAAC;AAC1F,eAAO,MAAM,gBAAgB,UAA6D,CAAC;AAC3F,eAAO,MAAM,kBAAkB,UAA6D,CAAC;AAC7F,eAAO,MAAM,cAAc,UAA6D,CAAC;AACzF,eAAO,MAAM,cAAc,UAA6D,CAAC;AAGzF,wBAAgB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAkBvD;AAED,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA6BnD,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAO9C,CAAC;AAWF,eAAO,MAAM,iBAAiB,EAAE,QAO/B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,QAO7B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,QAO/B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,QAO7B,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,QAO/B,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,QAOrC,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,QAOvC,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,QAOjC,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,QAOnC,CAAC;AAEF,eAAO,MAAM,cAAc,oBAAqC,CAAC;AACjE,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf"}