@jacksontian/equation-resolver 1.0.0 → 1.0.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/LICENSE +22 -0
- package/README.md +8 -2
- package/lib/evaluator.js +191 -5
- package/lib/fraction.js +10 -1
- package/package.json +8 -4
- package/.github/workflows/nodejs.yml +0 -31
- package/eslint.config.js +0 -63
- package/test/evaluator.test.js +0 -230
- package/test/fraction.test.js +0 -435
- package/test/lexer.test.js +0 -418
- package/test/parser.test.js +0 -264
- package/test/semantic-checker.test.js +0 -45
package/test/fraction.test.js
DELETED
|
@@ -1,435 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test';
|
|
2
|
-
import assert from 'node:assert';
|
|
3
|
-
import { Fraction } from '../lib/fraction.js';
|
|
4
|
-
|
|
5
|
-
describe('Fraction', () => {
|
|
6
|
-
describe('构造函数', () => {
|
|
7
|
-
it('创建整数分数', () => {
|
|
8
|
-
const f = new Fraction(5, 1);
|
|
9
|
-
assert.strictEqual(f.numerator, 5);
|
|
10
|
-
assert.strictEqual(f.denominator, 1);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('创建普通分数', () => {
|
|
14
|
-
const f = new Fraction(3, 4);
|
|
15
|
-
assert.strictEqual(f.numerator, 3);
|
|
16
|
-
assert.strictEqual(f.denominator, 4);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('自动约分', () => {
|
|
20
|
-
const f = new Fraction(6, 8);
|
|
21
|
-
assert.strictEqual(f.numerator, 3);
|
|
22
|
-
assert.strictEqual(f.denominator, 4);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('约分到最简形式', () => {
|
|
26
|
-
const f = new Fraction(12, 18);
|
|
27
|
-
assert.strictEqual(f.numerator, 2);
|
|
28
|
-
assert.strictEqual(f.denominator, 3);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('处理负数分子', () => {
|
|
32
|
-
const f = new Fraction(-3, 4);
|
|
33
|
-
assert.strictEqual(f.numerator, -3);
|
|
34
|
-
assert.strictEqual(f.denominator, 4);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('处理负数分母,自动转换符号', () => {
|
|
38
|
-
const f = new Fraction(3, -4);
|
|
39
|
-
assert.strictEqual(f.numerator, -3);
|
|
40
|
-
assert.strictEqual(f.denominator, 4);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('处理负分子和负分母', () => {
|
|
44
|
-
const f = new Fraction(-3, -4);
|
|
45
|
-
assert.strictEqual(f.numerator, 3);
|
|
46
|
-
assert.strictEqual(f.denominator, 4);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('分母为0时抛出错误', () => {
|
|
50
|
-
assert.throws(
|
|
51
|
-
() => new Fraction(1, 0),
|
|
52
|
-
(error) => {
|
|
53
|
-
assert.strictEqual(error.message, '分母不能为0');
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('默认分母为1', () => {
|
|
60
|
-
const f = new Fraction(5);
|
|
61
|
-
assert.strictEqual(f.numerator, 5);
|
|
62
|
-
assert.strictEqual(f.denominator, 1);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('处理零', () => {
|
|
66
|
-
const f = new Fraction(0, 5);
|
|
67
|
-
assert.strictEqual(f.numerator, 0);
|
|
68
|
-
assert.strictEqual(f.denominator, 1);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
describe('fromString', () => {
|
|
73
|
-
it('从整数字符串创建', () => {
|
|
74
|
-
const f = Fraction.fromString('5');
|
|
75
|
-
assert.strictEqual(f.numerator, 5);
|
|
76
|
-
assert.strictEqual(f.denominator, 1);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it('从正整数字符串创建', () => {
|
|
80
|
-
const f = Fraction.fromString('123');
|
|
81
|
-
assert.strictEqual(f.numerator, 123);
|
|
82
|
-
assert.strictEqual(f.denominator, 1);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('从负整数字符串创建', () => {
|
|
86
|
-
const f = Fraction.fromString('-5');
|
|
87
|
-
assert.strictEqual(f.numerator, -5);
|
|
88
|
-
assert.strictEqual(f.denominator, 1);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('从小数字符串创建', () => {
|
|
92
|
-
const f = Fraction.fromString('3.14');
|
|
93
|
-
assert.strictEqual(f.numerator, 157);
|
|
94
|
-
assert.strictEqual(f.denominator, 50);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('从小数字符串创建并约分', () => {
|
|
98
|
-
const f = Fraction.fromString('0.5');
|
|
99
|
-
assert.strictEqual(f.numerator, 1);
|
|
100
|
-
assert.strictEqual(f.denominator, 2);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it('从负小数字符串创建', () => {
|
|
104
|
-
const f = Fraction.fromString('-3.14');
|
|
105
|
-
assert.strictEqual(f.numerator, -157);
|
|
106
|
-
assert.strictEqual(f.denominator, 50);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('处理多位小数', () => {
|
|
110
|
-
const f = Fraction.fromString('0.123');
|
|
111
|
-
assert.strictEqual(f.numerator, 123);
|
|
112
|
-
assert.strictEqual(f.denominator, 1000);
|
|
113
|
-
});
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
describe('fromNumber', () => {
|
|
117
|
-
it('从整数创建', () => {
|
|
118
|
-
const f = Fraction.fromNumber(5);
|
|
119
|
-
assert.strictEqual(f.numerator, 5);
|
|
120
|
-
assert.strictEqual(f.denominator, 1);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it('从负整数创建', () => {
|
|
124
|
-
const f = Fraction.fromNumber(-5);
|
|
125
|
-
assert.strictEqual(f.numerator, -5);
|
|
126
|
-
assert.strictEqual(f.denominator, 1);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it('从浮点数创建', () => {
|
|
130
|
-
const f = Fraction.fromNumber(3.14);
|
|
131
|
-
assert.strictEqual(f.numerator, 157);
|
|
132
|
-
assert.strictEqual(f.denominator, 50);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('从0创建', () => {
|
|
136
|
-
const f = Fraction.fromNumber(0);
|
|
137
|
-
assert.strictEqual(f.numerator, 0);
|
|
138
|
-
assert.strictEqual(f.denominator, 1);
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
describe('add', () => {
|
|
143
|
-
it('两个分数相加', () => {
|
|
144
|
-
const f1 = new Fraction(1, 2);
|
|
145
|
-
const f2 = new Fraction(1, 3);
|
|
146
|
-
const result = f1.add(f2);
|
|
147
|
-
assert.strictEqual(result.numerator, 5);
|
|
148
|
-
assert.strictEqual(result.denominator, 6);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
it('分数与整数相加', () => {
|
|
152
|
-
const f = new Fraction(1, 2);
|
|
153
|
-
const result = f.add(1);
|
|
154
|
-
assert.strictEqual(result.numerator, 3);
|
|
155
|
-
assert.strictEqual(result.denominator, 2);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it('负数相加', () => {
|
|
159
|
-
const f1 = new Fraction(-1, 2);
|
|
160
|
-
const f2 = new Fraction(1, 2);
|
|
161
|
-
const result = f1.add(f2);
|
|
162
|
-
assert.strictEqual(result.numerator, 0);
|
|
163
|
-
assert.strictEqual(result.denominator, 1);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it('结果自动约分', () => {
|
|
167
|
-
const f1 = new Fraction(1, 4);
|
|
168
|
-
const f2 = new Fraction(1, 4);
|
|
169
|
-
const result = f1.add(f2);
|
|
170
|
-
assert.strictEqual(result.numerator, 1);
|
|
171
|
-
assert.strictEqual(result.denominator, 2);
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
it('零相加', () => {
|
|
175
|
-
const f1 = new Fraction(1, 2);
|
|
176
|
-
const f2 = new Fraction(0, 1);
|
|
177
|
-
const result = f1.add(f2);
|
|
178
|
-
assert.strictEqual(result.numerator, 1);
|
|
179
|
-
assert.strictEqual(result.denominator, 2);
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
describe('subtract', () => {
|
|
184
|
-
it('两个分数相减', () => {
|
|
185
|
-
const f1 = new Fraction(1, 2);
|
|
186
|
-
const f2 = new Fraction(1, 3);
|
|
187
|
-
const result = f1.subtract(f2);
|
|
188
|
-
assert.strictEqual(result.numerator, 1);
|
|
189
|
-
assert.strictEqual(result.denominator, 6);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it('分数减去整数', () => {
|
|
193
|
-
const f = new Fraction(3, 2);
|
|
194
|
-
const result = f.subtract(1);
|
|
195
|
-
assert.strictEqual(result.numerator, 1);
|
|
196
|
-
assert.strictEqual(result.denominator, 2);
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
it('负数相减', () => {
|
|
200
|
-
const f1 = new Fraction(1, 2);
|
|
201
|
-
const f2 = new Fraction(1, 2);
|
|
202
|
-
const result = f1.subtract(f2);
|
|
203
|
-
assert.strictEqual(result.numerator, 0);
|
|
204
|
-
assert.strictEqual(result.denominator, 1);
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
it('结果自动约分', () => {
|
|
208
|
-
const f1 = new Fraction(3, 4);
|
|
209
|
-
const f2 = new Fraction(1, 4);
|
|
210
|
-
const result = f1.subtract(f2);
|
|
211
|
-
assert.strictEqual(result.numerator, 1);
|
|
212
|
-
assert.strictEqual(result.denominator, 2);
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
describe('multiply', () => {
|
|
217
|
-
it('两个分数相乘', () => {
|
|
218
|
-
const f1 = new Fraction(1, 2);
|
|
219
|
-
const f2 = new Fraction(2, 3);
|
|
220
|
-
const result = f1.multiply(f2);
|
|
221
|
-
assert.strictEqual(result.numerator, 1);
|
|
222
|
-
assert.strictEqual(result.denominator, 3);
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it('分数与整数相乘', () => {
|
|
226
|
-
const f = new Fraction(1, 2);
|
|
227
|
-
const result = f.multiply(3);
|
|
228
|
-
assert.strictEqual(result.numerator, 3);
|
|
229
|
-
assert.strictEqual(result.denominator, 2);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it('负数相乘', () => {
|
|
233
|
-
const f1 = new Fraction(-1, 2);
|
|
234
|
-
const f2 = new Fraction(1, 2);
|
|
235
|
-
const result = f1.multiply(f2);
|
|
236
|
-
assert.strictEqual(result.numerator, -1);
|
|
237
|
-
assert.strictEqual(result.denominator, 4);
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
it('与零相乘', () => {
|
|
241
|
-
const f = new Fraction(1, 2);
|
|
242
|
-
const result = f.multiply(0);
|
|
243
|
-
assert.strictEqual(result.numerator, 0);
|
|
244
|
-
assert.strictEqual(result.denominator, 1);
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('结果自动约分', () => {
|
|
248
|
-
const f1 = new Fraction(2, 3);
|
|
249
|
-
const f2 = new Fraction(3, 4);
|
|
250
|
-
const result = f1.multiply(f2);
|
|
251
|
-
assert.strictEqual(result.numerator, 1);
|
|
252
|
-
assert.strictEqual(result.denominator, 2);
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
describe('divide', () => {
|
|
257
|
-
it('两个分数相除', () => {
|
|
258
|
-
const f1 = new Fraction(1, 2);
|
|
259
|
-
const f2 = new Fraction(1, 3);
|
|
260
|
-
const result = f1.divide(f2);
|
|
261
|
-
assert.strictEqual(result.numerator, 3);
|
|
262
|
-
assert.strictEqual(result.denominator, 2);
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
it('分数除以整数', () => {
|
|
266
|
-
const f = new Fraction(3, 2);
|
|
267
|
-
const result = f.divide(2);
|
|
268
|
-
assert.strictEqual(result.numerator, 3);
|
|
269
|
-
assert.strictEqual(result.denominator, 4);
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
it('整数除以分数', () => {
|
|
273
|
-
const f = new Fraction(1, 2);
|
|
274
|
-
const result = new Fraction(1, 1).divide(f);
|
|
275
|
-
assert.strictEqual(result.numerator, 2);
|
|
276
|
-
assert.strictEqual(result.denominator, 1);
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
it('除以零返回Infinity', () => {
|
|
280
|
-
const f = new Fraction(1, 2);
|
|
281
|
-
const result = f.divide(new Fraction(0, 1));
|
|
282
|
-
assert.strictEqual(result, Infinity);
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
it('负数相除', () => {
|
|
286
|
-
const f1 = new Fraction(-1, 2);
|
|
287
|
-
const f2 = new Fraction(1, 2);
|
|
288
|
-
const result = f1.divide(f2);
|
|
289
|
-
assert.strictEqual(result.numerator, -1);
|
|
290
|
-
assert.strictEqual(result.denominator, 1);
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
it('结果自动约分', () => {
|
|
294
|
-
const f1 = new Fraction(2, 3);
|
|
295
|
-
const f2 = new Fraction(4, 6);
|
|
296
|
-
const result = f1.divide(f2);
|
|
297
|
-
assert.strictEqual(result.numerator, 1);
|
|
298
|
-
assert.strictEqual(result.denominator, 1);
|
|
299
|
-
});
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
describe('negate', () => {
|
|
303
|
-
it('正数取负', () => {
|
|
304
|
-
const f = new Fraction(3, 4);
|
|
305
|
-
const result = f.negate();
|
|
306
|
-
assert.strictEqual(result.numerator, -3);
|
|
307
|
-
assert.strictEqual(result.denominator, 4);
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
it('负数取负', () => {
|
|
311
|
-
const f = new Fraction(-3, 4);
|
|
312
|
-
const result = f.negate();
|
|
313
|
-
assert.strictEqual(result.numerator, 3);
|
|
314
|
-
assert.strictEqual(result.denominator, 4);
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
it('零取负', () => {
|
|
318
|
-
const f = new Fraction(0, 1);
|
|
319
|
-
const result = f.negate();
|
|
320
|
-
assert.strictEqual(result.isZero(), true);
|
|
321
|
-
});
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
describe('toNumber', () => {
|
|
325
|
-
it('转换为数字', () => {
|
|
326
|
-
const f = new Fraction(1, 2);
|
|
327
|
-
assert.strictEqual(f.toNumber(), 0.5);
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
it('整数转换为数字', () => {
|
|
331
|
-
const f = new Fraction(5, 1);
|
|
332
|
-
assert.strictEqual(f.toNumber(), 5);
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
it('负数转换为数字', () => {
|
|
336
|
-
const f = new Fraction(-3, 4);
|
|
337
|
-
assert.strictEqual(f.toNumber(), -0.75);
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
it('零转换为数字', () => {
|
|
341
|
-
const f = new Fraction(0, 1);
|
|
342
|
-
assert.strictEqual(f.toNumber(), 0);
|
|
343
|
-
});
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
describe('isFinite', () => {
|
|
347
|
-
it('有限分数返回true', () => {
|
|
348
|
-
const f = new Fraction(1, 2);
|
|
349
|
-
assert.strictEqual(f.isFinite(), true);
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
it('整数返回true', () => {
|
|
353
|
-
const f = new Fraction(5, 1);
|
|
354
|
-
assert.strictEqual(f.isFinite(), true);
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
it('负数返回true', () => {
|
|
358
|
-
const f = new Fraction(-3, 4);
|
|
359
|
-
assert.strictEqual(f.isFinite(), true);
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
it('零返回true', () => {
|
|
363
|
-
const f = new Fraction(0, 1);
|
|
364
|
-
assert.strictEqual(f.isFinite(), true);
|
|
365
|
-
});
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
describe('isZero', () => {
|
|
369
|
-
it('零返回true', () => {
|
|
370
|
-
const f = new Fraction(0, 1);
|
|
371
|
-
assert.strictEqual(f.isZero(), true);
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
it('零分子返回true', () => {
|
|
375
|
-
const f = new Fraction(0, 5);
|
|
376
|
-
assert.strictEqual(f.isZero(), true);
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
it('非零返回false', () => {
|
|
380
|
-
const f = new Fraction(1, 2);
|
|
381
|
-
assert.strictEqual(f.isZero(), false);
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
it('负数返回false', () => {
|
|
385
|
-
const f = new Fraction(-1, 2);
|
|
386
|
-
assert.strictEqual(f.isZero(), false);
|
|
387
|
-
});
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
describe('valueOf', () => {
|
|
391
|
-
it('返回数值', () => {
|
|
392
|
-
const f = new Fraction(1, 2);
|
|
393
|
-
assert.strictEqual(f.valueOf(), 0.5);
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
it('可用于数值比较', () => {
|
|
397
|
-
const f1 = new Fraction(1, 2);
|
|
398
|
-
const f2 = new Fraction(2, 4);
|
|
399
|
-
assert.strictEqual(f1.valueOf(), f2.valueOf());
|
|
400
|
-
});
|
|
401
|
-
});
|
|
402
|
-
|
|
403
|
-
describe('复杂场景', () => {
|
|
404
|
-
it('链式运算', () => {
|
|
405
|
-
const f1 = new Fraction(1, 2);
|
|
406
|
-
const f2 = new Fraction(1, 3);
|
|
407
|
-
const f3 = new Fraction(1, 4);
|
|
408
|
-
const result = f1.add(f2).multiply(f3);
|
|
409
|
-
assert.strictEqual(result.numerator, 5);
|
|
410
|
-
assert.strictEqual(result.denominator, 24);
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
it('大数约分', () => {
|
|
414
|
-
const f = new Fraction(100, 200);
|
|
415
|
-
assert.strictEqual(f.numerator, 1);
|
|
416
|
-
assert.strictEqual(f.denominator, 2);
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
it('互质数保持原样', () => {
|
|
420
|
-
const f = new Fraction(7, 11);
|
|
421
|
-
assert.strictEqual(f.numerator, 7);
|
|
422
|
-
assert.strictEqual(f.denominator, 11);
|
|
423
|
-
});
|
|
424
|
-
|
|
425
|
-
it('分数运算保持精度', () => {
|
|
426
|
-
const f1 = Fraction.fromString('0.1');
|
|
427
|
-
const f2 = Fraction.fromString('0.2');
|
|
428
|
-
const result = f1.add(f2);
|
|
429
|
-
assert.strictEqual(result.numerator, 3);
|
|
430
|
-
assert.strictEqual(result.denominator, 10);
|
|
431
|
-
assert.strictEqual(result.toNumber(), 0.3);
|
|
432
|
-
});
|
|
433
|
-
});
|
|
434
|
-
});
|
|
435
|
-
|