src/Rat.test.ts   A
last analyzed

Complexity

Total Complexity 1
Complexity/F 0

Size

Lines of Code 644
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 505
dl 0
loc 644
rs 10
c 0
b 0
f 0
wmc 1
mnd 1
bc 1
fnc 0
bpm 0
cpm 0
noi 0
1
import Rat, { floatToRat, parseRat } from './Rat'
2
3
test('New Rat is the expected type', () => {
4
  const a = new Rat()
5
  expect(typeof a).toBe('object')
6
  expect(a.constructor.name).toBe('Rat')
7
})
8
9
test('Value of -13 is -13', () => {
10
  const a = new Rat(-13)
11
  expect(+a).toBe(-13)
12
})
13
14
test('Text representation of 69/1 is "69"', () => {
15
  const a = new Rat(69, 1)
16
  expect(a.toString()).toBe('69')
17
})
18
19
test('Text representation of -222/840 is "-37/140"', () => {
20
  const a = new Rat(-222, 840)
21
  expect(a.toString()).toBe('-37/140')
22
})
23
24
test('Profile of 1/2 is as expected', () => {
25
  const a = new Rat(1, 2)
26
  expect(a.profile).toBe(
27
    'Rat: 1/2 (≈0.5)' +
28
      '\n' +
29
      'Mixed: 1/2' +
30
      '\n' +
31
      'Continued: [0; 2]' +
32
      '\n' +
33
      'Factorization: 2^-1' +
34
      '\n' +
35
      'Egyptian: 1/2' +
36
      '\n' +
37
      'Babylonian: 30 * 60^-1' +
38
      '\n' +
39
      'psin(t): 4/5' +
40
      '\n' +
41
      'pcos(t): 3/5' +
42
      '\n' +
43
      'ptan(t): 4/3',
44
  )
45
})
46
47
test('Profile of 7/5 is as expected', () => {
48
  const a = new Rat(7, 5)
49
  expect(a.profile).toBe(
50
    'Rat: 7/5 (≈1.4)' +
51
      '\n' +
52
      'Mixed: 1 + 2/5' +
53
      '\n' +
54
      'Continued: [1; 2, 2]' +
55
      '\n' +
56
      'Factorization: 5^-1 * 7' +
57
      '\n' +
58
      'Egyptian: 1 + 1/3 + 1/15' +
59
      '\n' +
60
      'Babylonian: 1 * 60^0 + 23 * 60^-1 + 59 * 60^-2 + 59 * 60^-3 + 59 * 60^-4 + 59 * 60^-5 + 59 * 60^-6 + 59 * 60^-7 + 59 * 60^-8 + 58 * 60^-9 + 48 * 60^-10 + 23 * 60^-11 + 37 * 60^-12 + 11 * 60^-13 + 14 * 60^-14 + 17 * 60^-15 + 40 * 60^-16 + 29 * 60^-17 + 4 * 60^-18 + 13 * 60^-19 + 54 * 60^-21 + 29 * 60^-22 + 31 * 60^-23 + 52 * 60^-24 + 30 * 60^-25' +
61
      '\n' +
62
      'psin(t): 35/37' +
63
      '\n' +
64
      'pcos(t): -12/37' +
65
      '\n' +
66
      'ptan(t): -35/12',
67
  )
68
})
69
70
test('Profile of 420/69 is as expected', () => {
71
  const a = new Rat(420, 69)
72
  expect(a.profile).toBe(
73
    'Rat: 140/23 (≈6.086956521739131)' +
74
      '\n' +
75
      'Mixed: 6 + 2/23' +
76
      '\n' +
77
      'Continued: [6; 11, 2]' +
78
      '\n' +
79
      'Factorization: 2^2 * 5 * 7 * 23^-1' +
80
      '\n' +
81
      'Egyptian: 6 + 1/12 + 1/276' +
82
      '\n' +
83
      'Babylonian: 6 * 60^0 + 5 * 60^-1 + 13 * 60^-2 + 2 * 60^-3 + 36 * 60^-4 + 31 * 60^-5 + 18 * 60^-6 + 15 * 60^-7 + 39 * 60^-8 + 11 * 60^-9 + 43 * 60^-10 + 3 * 60^-11 + 50 * 60^-12 + 54 * 60^-13 + 39 * 60^-14 + 28 * 60^-15 + 27 * 60^-16 + 6 * 60^-17 + 56 * 60^-18 + 41 * 60^-19 + 2 * 60^-20 + 15 * 60^-21 + 21 * 60^-22 + 5 * 60^-23 + 37 * 60^-24 + 30 * 60^-25' +
84
      '\n' +
85
      'psin(t): 6440/20129' +
86
      '\n' +
87
      'pcos(t): -19071/20129' +
88
      '\n' +
89
      'ptan(t): -6440/19071',
90
  )
91
})
92
93
// @todo too slow
94
// test('Profile of 355/113 is as expected', () => {
95
//   const a = new Rat(355, 113)
96
//   expect(a.profile).toBe(
97
//     'Rat: 355/113 (≈3.1415929203539825)'
98
//     + '\n' + 'Mixed: 3 + 16/113'
99
//     + '\n' + 'Continued: [3; 7, 16]'
100
//     + '\n' + 'Factorization: 5 * 71 * 113^-1'
101
//     + '\n' + 'Egyptian: 3 + 1/8 + 1/61 + 1/5014 + 1/27649202 + 1/1911195900442808'
102
//     + '\n' + 'Babylonian: 3 * 60^0 + 8 * 60^-1 + 29 * 60^-2 + 44 * 60^-3 + 4 * 60^-4 + 14 * 60^-5 + 52 * 60^-6 + 2 * 60^-7 + 7 * 60^-8 + 28 * 60^-9 + 14 * 60^-10 + 8 * 60^-11 + 8 * 60^-12 + 24 * 60^-13 + 46 * 60^-14 + 42 * 60^-15 + 33 * 60^-16 + 4 * 60^-17 + 54 * 60^-18 + 49 * 60^-19 + 5 * 60^-20 + 12 * 60^-21 + 53 * 60^-22 + 26 * 60^-23 + 15 * 60^-24'
103
//     + '\n' + 'psin(t): 40115/69397'
104
//     + '\n' + 'pcos(t): -56628/69397'
105
//     + '\n' + 'ptan(t): -40115/56628'
106
//   )
107
// })
108
109
test('Default is zero', () => {
110
  const a = new Rat()
111
  expect(+a).toBe(0)
112
})
113
114
test('One is one', () => {
115
  const a = new Rat(1)
116
  expect(+a).toBe(1)
117
})
118
119
test('Cloning maintains the value', () => {
120
  const a = new Rat(42, -69)
121
  const b = a.clone()
122
  expect(+a).toBe(+b)
123
})
124
125
test('Mutating a clone does not affect the value of the original', () => {
126
  const a = new Rat(42, -69)
127
  const original = +a
128
  const b = a.clone()
129
  b.n = 33n
130
  expect(+a).toBe(original)
131
})
132
133
// test('The reciprocol of zero divided by a negative number is negative infinity', () => {
134
//   const a = new Rat(0, -69)
135
//   expect(+a.inv()).toBe(-Infinity)
136
// })
137
138
test('A non-zero integer divided by zero is infinity', () => {
139
  const a = new Rat(13, 0)
140
  expect(+a).toBe(Infinity)
141
})
142
143
test('Zero divided by zero is not a number', () => {
144
  const a = new Rat(0, 0)
145
  expect(+a).toBe(NaN)
146
})
147
148
test('Zero over a positive number is still zero', () => {
149
  const a = new Rat(0, 21)
150
  expect(+a).toBe(0)
151
})
152
153
// test('Zero over a negative number is negative zero', () => {
154
//   const a = new Rat(0, -21)
155
//   expect(+a).toBe(-0)
156
// })
157
158
test('The denominator of zero divided by a number greater than zero is normalized to one', () => {
159
  const a = new Rat(0, 42)
160
  const b = new Rat(1, 0)
161
  expect(+a.mediant(b)).toBe(1)
162
})
163
164
test('Zero plus zero is zero', () => {
165
  const a = new Rat()
166
  const b = new Rat()
167
  expect(+a.add(b)).toBe(0)
168
})
169
170
test('One plus one is two', () => {
171
  const a = new Rat(1)
172
  const b = new Rat(1)
173
  expect(+a.add(b)).toBe(2)
174
})
175
176
test('5/7 minus 21/2 is -137/14', () => {
177
  const a = new Rat(5, 7)
178
  const b = new Rat(21, 2)
179
  expect(a.sub(b).toString()).toBe('-137/14')
180
})
181
182
test('Five times three is fifteen', () => {
183
  const a = new Rat(5)
184
  const b = new Rat(3)
185
  expect(+a.mul(b)).toBe(15)
186
})
187
188
test('-2/3 divided by 13/11 is -22/39', () => {
189
  const a = new Rat(-2, 3)
190
  const b = new Rat(13, 11)
191
  expect(+a.div(b)).toBe(-22 / 39)
192
})
193
194
test('Mediant of 0/1 and 1/1 is 1/2', () => {
195
  const a = new Rat()
196
  const b = new Rat(1)
197
  expect(+a.mediant(b)).toBe(1 / 2)
198
})
199
200
test('-33 to the power of 0 is 1', () => {
201
  const a = new Rat(-11)
202
  const b = new Rat(0)
203
  expect(+a.pow(b)).toBe(1)
204
})
205
206
test('8 to the power of 2/3 is 4', () => {
207
  const a = new Rat(8)
208
  const b = new Rat(2, 3)
209
  expect(+a.pow(b)).toBeCloseTo(4)
210
})
211
212
test('5 to the power of 2 is 25', () => {
213
  const a = new Rat(5)
214
  const b = new Rat(2)
215
  expect(+a.pow(b)).toBe(25)
216
})
217
218
test('Minimum of 3/5 and 5/3 is 5/3', () => {
219
  const a = new Rat(3, 5)
220
  const b = new Rat(5, 3)
221
  expect(+a.min(b)).toBe(3 / 5)
222
})
223
224
test('Minimum of -3/5 and -5/3 is -5/3', () => {
225
  const a = new Rat(-3, 5)
226
  const b = new Rat(-5, 3)
227
  expect(+a.min(b)).toBe(-5 / 3)
228
})
229
230
test('Maximum of 7/15 and -5/3 is 7/15', () => {
231
  const a = new Rat(7, 15)
232
  const b = new Rat(-5, 3)
233
  expect(+a.max(b)).toBe(7 / 15)
234
})
235
236
test('Maximum of -7/15 and 5/3 is 5/3', () => {
237
  const a = new Rat(-7, 15)
238
  const b = new Rat(5, 3)
239
  expect(+a.max(b)).toBe(5 / 3)
240
})
241
242
test('Dot product of 3/5 and 7/3 is 36', () => {
243
  const a = new Rat(3, 5)
244
  const b = new Rat(7, 3)
245
  expect(Number(a.dot(b))).toBe(36)
246
})
247
248
test('7/3 equals 7/3', () => {
249
  const a = new Rat(7, 3)
250
  const b = new Rat(7, 3)
251
  expect(a.equals(b)).toBe(true)
252
})
253
254
test('7/3 does not equal 5/3', () => {
255
  const a = new Rat(7, 3)
256
  const b = new Rat(5, 3)
257
  expect(a.equals(b)).toBe(false)
258
})
259
260
test('7/3 approximates 7/3', () => {
261
  const a = new Rat(7, 3)
262
  const b = new Rat(7, 3)
263
  expect(a.approximates(+b)).toBe(true)
264
})
265
266
test('7/3 does not approximate 47/3', () => {
267
  const a = new Rat(7, 3)
268
  const b = new Rat(37, 3)
269
  expect(a.approximates(+b)).toBe(false)
270
})
271
272
test('1/100000000000000001 approximates 1/100000000000000002', () => {
273
  const a = new Rat(1, 100000000000000001n)
274
  const b = new Rat(1, 100000000000000002n)
275
  expect(a.approximates(+b)).toBe(true)
276
})
277
278
test('13/3 is greater than 12/3', () => {
279
  const a = new Rat(13, 3)
280
  const b = new Rat(12, 3)
281
  expect(a.isGreaterThan(b)).toBe(true)
282
})
283
284
test('11/3 is less than 12/3', () => {
285
  const a = new Rat(11, 3)
286
  const b = new Rat(12, 3)
287
  expect(a.isLessThan(b)).toBe(true)
288
})
289
290
test('Absolute value of -3 is 3', () => {
291
  const a = new Rat(-1)
292
  expect(+a.abs()).toBe(1)
293
})
294
295
test('Absolute value of 5 is 5', () => {
296
  const a = new Rat(5)
297
  expect(+a.abs()).toBe(5)
298
})
299
300
test('Opposite of -3/2 is 3/2', () => {
301
  const a = new Rat(-3, 2)
302
  expect(+a.neg()).toBe(3 / 2)
303
})
304
305
test('6/4 is not negative', () => {
306
  const a = new Rat(6, 4)
307
  expect(a.isNegative()).toBe(false)
308
})
309
310
test('-7/4 is negative', () => {
311
  const a = new Rat(-7, 4)
312
  expect(a.isNegative()).toBe(true)
313
})
314
315
test('-71/9 is finite', () => {
316
  const a = new Rat(-71, 9)
317
  expect(a.isFinite()).toBe(true)
318
})
319
320
test('Infinity is not finite', () => {
321
  const a = floatToRat(Infinity)
322
  expect(a.isFinite()).toBe(false)
323
})
324
325
test('Reciprocol of -3/5 is -5/3', () => {
326
  const a = new Rat(-3, 5)
327
  expect(+a.inv()).toBe(-5 / 3)
328
})
329
330
test('Square root of one is one', () => {
331
  const a = new Rat(1)
332
  expect(+a.root(2)).toBe(1)
333
})
334
335
test('Square root of 256 is 16', () => {
336
  const a = new Rat(256)
337
  expect(+a.sqrt()).toBe(16)
338
})
339
340
test('5th root of 759375/16807 is 15/7', () => {
341
  const a = new Rat(759375, 16807)
342
  const n = 5
343
  expect(+a.root(n)).toBe(15 / 7)
344
})
345
346
test('Root of infinity is also infinity', () => {
347
  const a = new Rat(1, 0)
348
  const n = 7
349
  expect(+a.root(n)).toBe(Infinity)
350
})
351
352
test('Root of a negative throws up', () => {
353
  const a = new Rat(-1)
354
  expect(() => {
355
    a.sqrt()
356
  }).toThrow(
357
    'Roots of negative numbers like -1 are too complex for this basic library',
358
  )
359
})
360
361
test('4242/666 is rounded to 6', () => {
362
  const a = new Rat(4242, 666)
363
  expect(Number(a.round())).toBe(6)
364
})
365
366
test('Flooring 420.69 is 420', () => {
367
  const a = floatToRat(420.69)
368
  expect(a.floor()).toBe(420n)
369
})
370
371
test('Flooring -42.69 is -43', () => {
372
  const a = floatToRat(-42.69)
373
  expect(a.floor()).toBe(-43n)
374
})
375
376
test('Ceilinging -420.69 is -420', () => {
377
  const a = floatToRat(-420.69)
378
  expect(a.ceil()).toBe(-420n)
379
})
380
381
test('psin(0) = 0', () => {
382
  const a = new Rat(0)
383
  expect(+a.psin()).toBe(0)
384
})
385
386
test('psin(1) = 1', () => {
387
  const a = new Rat(1)
388
  expect(+a.psin()).toBe(1)
389
})
390
391
test('psin(-1) = -1', () => {
392
  const a = new Rat(-1)
393
  expect(+a.psin()).toBe(-1)
394
})
395
396
test('psin(Infinity) = 0', () => {
397
  const a = floatToRat(Infinity)
398
  expect(+a.psin()).toBe(0)
399
})
400
401
test('psin(1/2) = 4/5', () => {
402
  const a = new Rat(1, 2)
403
  expect(a.psin().toString()).toBe('4/5')
404
})
405
406
test('psin(2) = 4/5', () => {
407
  const a = new Rat(2)
408
  expect(a.psin().toString()).toBe('4/5')
409
})
410
411
test('psin(3) = 3/5', () => {
412
  const a = new Rat(3)
413
  expect(a.psin().toString()).toBe('3/5')
414
})
415
416
test('pcos(0) = 1', () => {
417
  const a = new Rat(0)
418
  expect(+a.pcos()).toBe(1)
419
})
420
421
test('pcos(1) = 0', () => {
422
  const a = new Rat(1)
423
  expect(+a.pcos()).toBe(0)
424
})
425
426
test('pcos(-1) = 0', () => {
427
  const a = new Rat(-1)
428
  expect(+a.pcos()).toBe(0)
429
})
430
431
test('pcos(Infinity) = -1', () => {
432
  const a = floatToRat(Infinity)
433
  expect(+a.pcos()).toBe(-1)
434
})
435
436
test('pcos(1/2) = 3/5', () => {
437
  const a = new Rat(1, 2)
438
  expect(a.pcos().toString()).toBe('3/5')
439
})
440
441
test('pcos(2) = -3/5', () => {
442
  const a = new Rat(2)
443
  expect(a.pcos().toString()).toBe('-3/5')
444
})
445
446
test('pcos(3) = -4/5', () => {
447
  const a = new Rat(3)
448
  expect(a.pcos().toString()).toBe('-4/5')
449
})
450
451
test('ptan(0) = 0', () => {
452
  const a = new Rat(0)
453
  expect(+a.ptan()).toBe(0)
454
})
455
456
test('ptan(1) = Infinity', () => {
457
  const a = new Rat(1)
458
  expect(+a.ptan()).toBe(Infinity)
459
})
460
461
test('ptan(-1) = -1/0', () => {
462
  const a = new Rat(-1)
463
  expect(a.ptan().toString()).toBe('-1/0')
464
})
465
466
test('ptan(Infinity) = 0', () => {
467
  const a = floatToRat(Infinity)
468
  expect(+a.ptan()).toBe(0)
469
})
470
471
test('Mixed fraction of -33/5 is "-6 + -3/5"', () => {
472
  const a = new Rat(-33, 5)
473
  expect(a.mixedFractionString()).toBe('-6 + -3/5')
474
})
475
476
test('Continued fraction of 0 is "[0]"', () => {
477
  const a = new Rat(0)
478
  expect(a.continuedFractionString()).toBe('[0]')
479
})
480
481
test('Continued fraction of 1 is "[1]"', () => {
482
  const a = new Rat(1)
483
  expect(a.continuedFractionString()).toBe('[1]')
484
})
485
486
test('Continued fraction of Infinity is "[]"', () => {
487
  const a = new Rat(1, 0)
488
  expect(a.continuedFractionString()).toBe('[]')
489
})
490
491
test('Continued fraction coefficients of 6/9 are [0, 1, 2]', () => {
492
  const a = new Rat(6, 9)
493
  const ex = [0, 1, 2]
494
  const r = []
495
  for (const n of a.continuedFraction()) {
496
    r.push(n)
497
  }
498
  expect(r).toStrictEqual(ex)
499
})
500
501
test('Continued fraction of 2 is "[2]"', () => {
502
  const a = new Rat(2)
503
  expect(a.continuedFractionString()).toBe('[2]')
504
})
505
506
test('Continued fraction of 1/2 is "[0; 2]"', () => {
507
  const a = new Rat(1, 2)
508
  expect(a.continuedFractionString()).toBe('[0; 2]')
509
})
510
511
test('Continued fraction of 5/7 is "[0; 1, 2]"', () => {
512
  const a = new Rat(5, 7)
513
  expect(a.continuedFractionString()).toBe('[0; 1, 2, 2]')
514
})
515
516
test('Prime factorization of 360 is "2^3 * 3^2 * 5"', () => {
517
  const a = new Rat(360)
518
  expect(a.primeFactorizationString()).toBe('2^3 * 3^2 * 5')
519
})
520
521
test('Prime factorization of 36/31 is "2^2 * 3^2 * 31^-1"', () => {
522
  const a = new Rat(36, 31)
523
  expect(a.primeFactorizationString()).toBe('2^2 * 3^2 * 31^-1')
524
})
525
526
test('Prime factorization of 53155782/127979960268013673033516151007 is "?"', () => {
527
  const a = new Rat(53155782n, 127979960268013673033516151007n)
528
  expect(a.primeFactorizationString()).toBe(
529
    '2 * 3^2 * 29 * 79 * 433^-1 * 1279^-3 * 1289 * 19387^-4',
530
  )
531
})
532
533
test('Prime factorization of 17/360 is "2^-3 * 3^-2 * 5^-1 * 17"', () => {
534
  const a = new Rat(17, 360)
535
  expect(a.primeFactorizationString()).toBe('2^-3 * 3^-2 * 5^-1 * 17')
536
})
537
538
test('Egyptian fraction for 5/8 is "1/2 + 1/8"', () => {
539
  const a = new Rat(5, 8)
540
  expect(a.egyptianFractionString()).toBe('1/2 + 1/8')
541
})
542
543
test('Egyptian fraction for 17/360 is "1/22 + 1/566 + 1/1120680"', () => {
544
  const a = new Rat(17, 360)
545
  expect(a.egyptianFractionString()).toBe('1/22 + 1/566 + 1/1120680')
546
})
547
548
test('Egyptian fraction for -1/12 is "-1 + 1/2 + 1/3 + 1/12"', () => {
549
  const a = new Rat(-1, 12)
550
  expect(a.egyptianFractionString()).toBe('-1 + 1/2 + 1/3 + 1/12')
551
})
552
553
test('Egyptian fraction for 4096 is as expected', () => {
554
  const a = new Rat(4096)
555
  expect(a.egyptianFractionString()).toBe('4096')
556
})
557
558
test('Babylonian fraction for 1/60 is as expected', () => {
559
  const a = new Rat(1, 60)
560
  expect(a.babylonianFractionString()).toBe('1 * 60^-1')
561
})
562
563
test('Babylonian fraction for 2/3 is as expected', () => {
564
  const a = new Rat(2, 3)
565
  expect(a.babylonianFractionString()).toBe('40 * 60^-1')
566
})
567
568
test('Babylonian fraction for 666/360 is as expected', () => {
569
  const a = new Rat(666, 360)
570
  expect(a.babylonianFractionString()).toBe('1 * 60^0 + 51 * 60^-1')
571
})
572
573
test('Babylonian fraction for 181237/10 is "5 * 60^2 + 2 * 60^1 + 3 * 60^0 + 42 * 60^-1"', () => {
574
  const a = new Rat(181237, 10)
575
  expect(a.babylonianFractionString()).toBe(
576
    '5 * 60^2 + 2 * 60^1 + 3 * 60^0 + 42 * 60^-1',
577
  )
578
})
579
580
test('Babylonian fraction for 420 is as expected', () => {
581
  const a = new Rat(420)
582
  expect(a.babylonianFractionString()).toBe('7 * 60^1')
583
})
584
585
test('0.5 is converted to "1/2"', () => {
586
  const n = 0.5
587
  expect(floatToRat(n).toString()).toBe('1/2')
588
})
589
590
test('Not a number is converted to "0/0"', () => {
591
  const n = 0 / 0
592
  expect(floatToRat(n).toString()).toBe('0/0')
593
})
594
595
test('Infinity is converted to "1/0"', () => {
596
  const n = Infinity
597
  expect(floatToRat(n).toString()).toBe('1/0')
598
})
599
600
test('-Infinity is converted to "-1/0"', () => {
601
  const n = -Infinity
602
  expect(floatToRat(n).toString()).toBe('-1/0')
603
})
604
605
test('42069 is converted to "42069"', () => {
606
  const n = 42069
607
  expect(floatToRat(n).toString()).toBe('42069')
608
})
609
610
test('-1/42069 is converted to "-1/42069"', () => {
611
  const n = -1 / 42069
612
  expect(floatToRat(n).toString()).toBe('-1/42069')
613
})
614
615
test('-420/69 converted to a float and back to a Rat is "-140/23"', () => {
616
  const a = new Rat(-420, 69)
617
  expect(floatToRat(+a).toString()).toBe('-140/23')
618
})
619
620
test('Not a number is converted to "0/0"', () => {
621
  const n = 'NaN'
622
  expect(parseRat(n).toString()).toBe('0/0')
623
})
624
625
test('"Infinity" is converted to "1/0"', () => {
626
  const n = 'Infinity'
627
  expect(parseRat(n).toString()).toBe('1/0')
628
})
629
630
test('"-Infinity" is converted to "-1/0"', () => {
631
  const n = '-Infinity'
632
  expect(parseRat(n).toString()).toBe('-1/0')
633
})
634
635
test('"420" converted to a Rat is "420"', () => {
636
  const a = '420'
637
  expect(parseRat(a).toString()).toBe('420')
638
})
639
640
test('"-420/69" converted to a Rat is "-140/23"', () => {
641
  const a = '-420/69'
642
  expect(parseRat(a).toString()).toBe('-140/23')
643
})
644