@keplr-wallet/unit 0.9.9-rc.0 → 0.9.11-rc.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/build/coin-pretty.d.ts +13 -3
- package/build/coin-pretty.js +36 -25
- package/build/coin-pretty.js.map +1 -1
- package/build/coin-pretty.spec.js +194 -9
- package/build/coin-pretty.spec.js.map +1 -1
- package/build/coin-utils.js +8 -4
- package/build/coin-utils.js.map +1 -1
- package/build/coin-utils.spec.js +16 -0
- package/build/coin-utils.spec.js.map +1 -1
- package/build/coin.js +1 -1
- package/build/coin.js.map +1 -1
- package/build/coin.spec.js +15 -0
- package/build/coin.spec.js.map +1 -1
- package/build/dec-utils.d.ts +8 -1
- package/build/dec-utils.js +22 -20
- package/build/dec-utils.js.map +1 -1
- package/build/dec-utils.spec.js +19 -0
- package/build/dec-utils.spec.js.map +1 -1
- package/build/decimal.d.ts +18 -9
- package/build/decimal.js +63 -27
- package/build/decimal.js.map +1 -1
- package/build/decimal.spec.js +218 -2
- package/build/decimal.spec.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/int-pretty.d.ts +16 -4
- package/build/int-pretty.js +74 -36
- package/build/int-pretty.js.map +1 -1
- package/build/int-pretty.spec.js +261 -94
- package/build/int-pretty.spec.js.map +1 -1
- package/build/int.d.ts +14 -2
- package/build/int.js +48 -0
- package/build/int.js.map +1 -1
- package/build/int.spec.d.ts +1 -0
- package/build/int.spec.js +133 -0
- package/build/int.spec.js.map +1 -0
- package/build/price-pretty.d.ts +13 -3
- package/build/price-pretty.js +37 -26
- package/build/price-pretty.js.map +1 -1
- package/build/price-pretty.spec.js +59 -2
- package/build/price-pretty.spec.js.map +1 -1
- package/build/rate-pretty.d.ts +57 -0
- package/build/rate-pretty.js +128 -0
- package/build/rate-pretty.js.map +1 -0
- package/build/rate-pretty.spec.d.ts +1 -0
- package/build/rate-pretty.spec.js +38 -0
- package/build/rate-pretty.spec.js.map +1 -0
- package/package.json +3 -3
- package/src/coin-pretty.spec.ts +304 -11
- package/src/coin-pretty.ts +56 -29
- package/src/coin-utils.spec.ts +32 -0
- package/src/coin-utils.ts +12 -4
- package/src/coin.spec.ts +20 -0
- package/src/coin.ts +1 -1
- package/src/dec-utils.spec.ts +39 -0
- package/src/dec-utils.ts +25 -20
- package/src/decimal.spec.ts +269 -2
- package/src/decimal.ts +84 -54
- package/src/index.ts +1 -0
- package/src/int-pretty.spec.ts +296 -101
- package/src/int-pretty.ts +87 -34
- package/src/int.spec.ts +178 -0
- package/src/int.ts +66 -2
- package/src/price-pretty.spec.ts +106 -2
- package/src/price-pretty.ts +50 -30
- package/src/rate-pretty.spec.ts +52 -0
- package/src/rate-pretty.ts +165 -0
package/src/dec-utils.ts
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
import { Dec } from "./decimal";
|
2
|
+
import { Int } from "./int";
|
2
3
|
|
3
4
|
export class DecUtils {
|
4
|
-
static trim(dec: Dec | string): string {
|
5
|
+
public static trim(dec: Dec | string): string {
|
5
6
|
let decStr = typeof dec === "string" ? dec : dec.toString();
|
6
7
|
|
7
8
|
if (decStr.indexOf(".") < 0) {
|
@@ -25,33 +26,37 @@ export class DecUtils {
|
|
25
26
|
return decStr;
|
26
27
|
}
|
27
28
|
|
28
|
-
|
29
|
+
protected static tenExponentNs: { [n: string]: Dec } = {};
|
29
30
|
|
30
|
-
static
|
31
|
-
if (
|
31
|
+
public static getTenExponentN(n: number): Dec {
|
32
|
+
if (n < -Dec.precision) {
|
33
|
+
// Dec can only handle up to precision 18.
|
34
|
+
// Anything less than 18 precision is 0, so there is a high probability of an error.
|
32
35
|
throw new Error("Too little precision");
|
33
36
|
}
|
34
|
-
if (precision > 18) {
|
35
|
-
throw new Error("Too much precision");
|
36
|
-
}
|
37
37
|
|
38
|
-
if (DecUtils.
|
39
|
-
return DecUtils.
|
38
|
+
if (DecUtils.tenExponentNs[n.toString()]) {
|
39
|
+
return DecUtils.tenExponentNs[n.toString()];
|
40
40
|
}
|
41
41
|
|
42
|
-
|
42
|
+
const dec = new Dec(10).pow(new Int(n));
|
43
|
+
DecUtils.tenExponentNs[n.toString()] = dec;
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
dec = dec.quo(new Dec(10));
|
51
|
-
}
|
45
|
+
return dec;
|
46
|
+
}
|
47
|
+
|
48
|
+
public static getTenExponentNInPrecisionRange(n: number): Dec {
|
49
|
+
if (n > Dec.precision) {
|
50
|
+
throw new Error("Too much precision");
|
52
51
|
}
|
53
52
|
|
54
|
-
DecUtils.
|
55
|
-
|
53
|
+
return DecUtils.getTenExponentN(n);
|
54
|
+
}
|
55
|
+
|
56
|
+
/**
|
57
|
+
* @deprecated Use`getTenExponentNInPrecisionRange`
|
58
|
+
*/
|
59
|
+
public static getPrecisionDec(precision: number): Dec {
|
60
|
+
return DecUtils.getTenExponentNInPrecisionRange(precision);
|
56
61
|
}
|
57
62
|
}
|
package/src/decimal.spec.ts
CHANGED
@@ -2,7 +2,19 @@ import { Dec } from "./decimal";
|
|
2
2
|
import { Int } from "./int";
|
3
3
|
|
4
4
|
describe("Test decimals", () => {
|
5
|
-
|
5
|
+
// (2 ** (256 + 60) - 1) / (10 ** 18)
|
6
|
+
const maxDec =
|
7
|
+
"133499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433535";
|
8
|
+
// maxDec + 0.000000000000000001
|
9
|
+
const overflowedDec =
|
10
|
+
"133499189745056880149688856635597007162669032647290798121690100488888732861290.034376435130433536";
|
11
|
+
|
12
|
+
it("dec should be parsed properly", () => {
|
13
|
+
expect(() => new Dec(1, 0)).not.toThrow();
|
14
|
+
expect(() => new Dec(1, -1)).toThrow();
|
15
|
+
expect(() => new Dec(1, Dec.precision)).not.toThrow();
|
16
|
+
expect(() => new Dec(1, Dec.precision + 1)).toThrow();
|
17
|
+
|
6
18
|
let dec = new Dec("10.009");
|
7
19
|
expect(dec.toString()).toBe("10.009000000000000000");
|
8
20
|
expect(dec.toString(2)).toBe("10.00");
|
@@ -14,6 +26,17 @@ describe("Test decimals", () => {
|
|
14
26
|
dec = new Dec("10");
|
15
27
|
expect(dec.toString()).toBe("10.000000000000000000");
|
16
28
|
|
29
|
+
dec = new Dec(10);
|
30
|
+
expect(dec.toString()).toBe("10.000000000000000000");
|
31
|
+
|
32
|
+
dec = new Dec(10.009);
|
33
|
+
expect(dec.toString()).toBe("10.009000000000000000");
|
34
|
+
expect(dec.toString(2)).toBe("10.00");
|
35
|
+
|
36
|
+
dec = new Dec(-123.456789);
|
37
|
+
expect(dec.toString()).toBe("-123.456789000000000000");
|
38
|
+
expect(dec.toString(3)).toBe("-123.456");
|
39
|
+
|
17
40
|
expect(() => {
|
18
41
|
new Dec("");
|
19
42
|
}).toThrow();
|
@@ -34,6 +57,147 @@ describe("Test decimals", () => {
|
|
34
57
|
}).toThrow();
|
35
58
|
});
|
36
59
|
|
60
|
+
it("Test Dec overflow", () => {
|
61
|
+
expect(new Dec(maxDec).toString()).toBe(maxDec);
|
62
|
+
expect(new Dec("-" + maxDec).toString()).toBe("-" + maxDec);
|
63
|
+
|
64
|
+
expect(() => new Dec(overflowedDec)).toThrow();
|
65
|
+
expect(() => new Dec("-" + overflowedDec)).toThrow();
|
66
|
+
|
67
|
+
const max = new Dec(maxDec);
|
68
|
+
expect(() => max.add(new Dec(1, Dec.precision))).toThrow();
|
69
|
+
|
70
|
+
const min = new Dec("-" + maxDec);
|
71
|
+
expect(() => min.sub(new Dec(1, Dec.precision))).toThrow();
|
72
|
+
});
|
73
|
+
|
74
|
+
it("Test Dec neg/abs", () => {
|
75
|
+
expect(new Dec(1).neg().toString()).toBe("-1.000000000000000000");
|
76
|
+
expect(new Dec(1).neg().equals(new Dec(-1))).toBe(true);
|
77
|
+
|
78
|
+
expect(new Dec(-1).neg().toString()).toBe("1.000000000000000000");
|
79
|
+
expect(new Dec(-1).neg().equals(new Dec(1))).toBe(true);
|
80
|
+
|
81
|
+
expect(new Dec(1).abs().toString()).toBe("1.000000000000000000");
|
82
|
+
expect(new Dec(1).abs().equals(new Dec(1))).toBe(true);
|
83
|
+
|
84
|
+
expect(new Dec(-1).abs().toString()).toBe("1.000000000000000000");
|
85
|
+
expect(new Dec(-1).abs().equals(new Dec(1))).toBe(true);
|
86
|
+
});
|
87
|
+
|
88
|
+
it("Test Dec isPositive/isNegative/isInteger/isZero", () => {
|
89
|
+
expect(new Dec(1).isPositive()).toBe(true);
|
90
|
+
expect(new Dec(-1).isPositive()).toBe(false);
|
91
|
+
|
92
|
+
expect(new Dec(1).isNegative()).toBe(false);
|
93
|
+
expect(new Dec(-1).isNegative()).toBe(true);
|
94
|
+
|
95
|
+
expect(new Dec(1).isInteger()).toBe(true);
|
96
|
+
expect(new Dec(-1).isInteger()).toBe(true);
|
97
|
+
|
98
|
+
expect(new Dec(1.1).isInteger()).toBe(false);
|
99
|
+
expect(new Dec(-1.1).isInteger()).toBe(false);
|
100
|
+
|
101
|
+
expect(new Dec(0).isZero()).toBe(true);
|
102
|
+
expect(new Dec(-0).isZero()).toBe(true);
|
103
|
+
expect(new Dec(-1.1).isZero()).toBe(false);
|
104
|
+
expect(new Dec(1.1).isZero()).toBe(false);
|
105
|
+
});
|
106
|
+
|
107
|
+
it("Test Dec comparison", () => {
|
108
|
+
const dec1 = new Dec(1);
|
109
|
+
const dec2 = new Dec(2);
|
110
|
+
|
111
|
+
expect(dec1.gt(dec2)).toBe(false);
|
112
|
+
expect(dec1.gte(dec1)).toBe(true);
|
113
|
+
|
114
|
+
expect(dec1.lt(dec2)).toBe(true);
|
115
|
+
expect(dec1.lte(dec1)).toBe(true);
|
116
|
+
|
117
|
+
expect(dec1.equals(dec2)).toBe(false);
|
118
|
+
expect(dec1.equals(dec1)).toBe(true);
|
119
|
+
});
|
120
|
+
|
121
|
+
it("Test Dec power", () => {
|
122
|
+
const tests: {
|
123
|
+
d1: Dec;
|
124
|
+
i1: Int;
|
125
|
+
exp: Dec;
|
126
|
+
}[] = [
|
127
|
+
{
|
128
|
+
d1: new Dec(0),
|
129
|
+
i1: new Int(12),
|
130
|
+
exp: new Dec(0),
|
131
|
+
},
|
132
|
+
{
|
133
|
+
d1: new Dec(0),
|
134
|
+
i1: new Int(0),
|
135
|
+
exp: new Dec(1),
|
136
|
+
},
|
137
|
+
{
|
138
|
+
d1: new Dec(12),
|
139
|
+
i1: new Int(0),
|
140
|
+
exp: new Dec(1),
|
141
|
+
},
|
142
|
+
{
|
143
|
+
d1: new Dec(-12),
|
144
|
+
i1: new Int(0),
|
145
|
+
exp: new Dec(1),
|
146
|
+
},
|
147
|
+
{
|
148
|
+
d1: new Dec(-12),
|
149
|
+
i1: new Int(1),
|
150
|
+
exp: new Dec(-12),
|
151
|
+
},
|
152
|
+
{
|
153
|
+
d1: new Dec(-12),
|
154
|
+
i1: new Int(2),
|
155
|
+
exp: new Dec(144),
|
156
|
+
},
|
157
|
+
{
|
158
|
+
d1: new Dec(12),
|
159
|
+
i1: new Int(3),
|
160
|
+
exp: new Dec(1728),
|
161
|
+
},
|
162
|
+
{
|
163
|
+
d1: new Dec(12),
|
164
|
+
i1: new Int(-1),
|
165
|
+
exp: new Dec("0.083333333333333333"),
|
166
|
+
},
|
167
|
+
{
|
168
|
+
d1: new Dec(12),
|
169
|
+
i1: new Int(-2),
|
170
|
+
exp: new Dec("0.006944444444444444"),
|
171
|
+
},
|
172
|
+
{
|
173
|
+
d1: new Dec(12),
|
174
|
+
i1: new Int(-3),
|
175
|
+
exp: new Dec("0.000578703703703704"),
|
176
|
+
},
|
177
|
+
{
|
178
|
+
d1: new Dec(10),
|
179
|
+
i1: new Int(4),
|
180
|
+
exp: new Dec("10000"),
|
181
|
+
},
|
182
|
+
{
|
183
|
+
d1: new Dec(10),
|
184
|
+
i1: new Int(5),
|
185
|
+
exp: new Dec("100000"),
|
186
|
+
},
|
187
|
+
{
|
188
|
+
d1: new Dec(10),
|
189
|
+
i1: new Int(-5),
|
190
|
+
exp: new Dec("0.00001"),
|
191
|
+
},
|
192
|
+
];
|
193
|
+
|
194
|
+
for (const test of tests) {
|
195
|
+
const res = test.d1.pow(test.i1);
|
196
|
+
|
197
|
+
expect(res.toString()).toBe(test.exp.toString());
|
198
|
+
}
|
199
|
+
});
|
200
|
+
|
37
201
|
it("dec should be caculated properly", () => {
|
38
202
|
const tests: {
|
39
203
|
d1: Dec;
|
@@ -160,6 +324,64 @@ describe("Test decimals", () => {
|
|
160
324
|
});
|
161
325
|
|
162
326
|
it("dec should be round up properly", () => {
|
327
|
+
const tests: {
|
328
|
+
d1: Dec;
|
329
|
+
exp: Int;
|
330
|
+
}[] = [
|
331
|
+
{
|
332
|
+
d1: new Dec("0.25"),
|
333
|
+
exp: new Int("1"),
|
334
|
+
},
|
335
|
+
{
|
336
|
+
d1: new Dec("0"),
|
337
|
+
exp: new Int("0"),
|
338
|
+
},
|
339
|
+
{
|
340
|
+
d1: new Dec("1"),
|
341
|
+
exp: new Int("1"),
|
342
|
+
},
|
343
|
+
{
|
344
|
+
d1: new Dec("0.75"),
|
345
|
+
exp: new Int("1"),
|
346
|
+
},
|
347
|
+
{
|
348
|
+
d1: new Dec("0.5"),
|
349
|
+
exp: new Int("1"),
|
350
|
+
},
|
351
|
+
{
|
352
|
+
d1: new Dec("7.5"),
|
353
|
+
exp: new Int("8"),
|
354
|
+
},
|
355
|
+
{
|
356
|
+
d1: new Dec("0.545"),
|
357
|
+
exp: new Int("1"),
|
358
|
+
},
|
359
|
+
{
|
360
|
+
d1: new Dec("1.545"),
|
361
|
+
exp: new Int("2"),
|
362
|
+
},
|
363
|
+
{
|
364
|
+
d1: new Dec("-1.545"),
|
365
|
+
exp: new Int("-1"),
|
366
|
+
},
|
367
|
+
{
|
368
|
+
d1: new Dec("-0.545"),
|
369
|
+
exp: new Int("0"),
|
370
|
+
},
|
371
|
+
];
|
372
|
+
|
373
|
+
for (const test of tests) {
|
374
|
+
const resPos = test.d1.roundUp();
|
375
|
+
expect(resPos.toString()).toBe(test.exp.toString());
|
376
|
+
|
377
|
+
const resPosDec = test.d1.roundUpDec();
|
378
|
+
expect(resPosDec.toString()).toBe(
|
379
|
+
test.exp.toString() + ".000000000000000000"
|
380
|
+
);
|
381
|
+
}
|
382
|
+
});
|
383
|
+
|
384
|
+
it("dec should be round properly", () => {
|
163
385
|
const tests: {
|
164
386
|
d1: Dec;
|
165
387
|
exp: Int;
|
@@ -202,12 +424,22 @@ describe("Test decimals", () => {
|
|
202
424
|
const resNeg = test.d1.neg().round();
|
203
425
|
expect(resNeg.toString()).toBe(test.exp.neg().toString());
|
204
426
|
|
427
|
+
const resNegDec = test.d1.neg().roundDec();
|
428
|
+
expect(resNegDec.toString()).toBe(
|
429
|
+
test.exp.neg().toString() + ".000000000000000000"
|
430
|
+
);
|
431
|
+
|
205
432
|
const resPos = test.d1.round();
|
206
433
|
expect(resPos.toString()).toBe(test.exp.toString());
|
434
|
+
|
435
|
+
const resPosDec = test.d1.roundDec();
|
436
|
+
expect(resPosDec.toString()).toBe(
|
437
|
+
test.exp.toString() + ".000000000000000000"
|
438
|
+
);
|
207
439
|
}
|
208
440
|
});
|
209
441
|
|
210
|
-
it("dec should be
|
442
|
+
it("dec should be truncated properly", () => {
|
211
443
|
const tests: {
|
212
444
|
d1: Dec;
|
213
445
|
exp: Int;
|
@@ -250,8 +482,18 @@ describe("Test decimals", () => {
|
|
250
482
|
const resNeg = test.d1.neg().truncate();
|
251
483
|
expect(resNeg.toString()).toBe(test.exp.neg().toString());
|
252
484
|
|
485
|
+
const resNegDec = test.d1.neg().truncateDec();
|
486
|
+
expect(resNegDec.toString()).toBe(
|
487
|
+
test.exp.neg().toString() + ".000000000000000000"
|
488
|
+
);
|
489
|
+
|
253
490
|
const resPos = test.d1.truncate();
|
254
491
|
expect(resPos.toString()).toBe(test.exp.toString());
|
492
|
+
|
493
|
+
const resPosDec = test.d1.truncateDec();
|
494
|
+
expect(resPosDec.toString()).toBe(
|
495
|
+
test.exp.toString() + ".000000000000000000"
|
496
|
+
);
|
255
497
|
}
|
256
498
|
});
|
257
499
|
|
@@ -281,6 +523,11 @@ describe("Test decimals", () => {
|
|
281
523
|
precision: 5,
|
282
524
|
exp: "1.00000",
|
283
525
|
},
|
526
|
+
{
|
527
|
+
d1: new Dec(new Int("1")),
|
528
|
+
precision: 5,
|
529
|
+
exp: "1.00000",
|
530
|
+
},
|
284
531
|
{
|
285
532
|
d1: new Dec("7.5"),
|
286
533
|
precision: 3,
|
@@ -291,6 +538,11 @@ describe("Test decimals", () => {
|
|
291
538
|
precision: 0,
|
292
539
|
exp: "100",
|
293
540
|
},
|
541
|
+
{
|
542
|
+
d1: new Dec(100.000000001),
|
543
|
+
precision: 0,
|
544
|
+
exp: "100",
|
545
|
+
},
|
294
546
|
{
|
295
547
|
d1: new Dec("-0.25"),
|
296
548
|
precision: 0,
|
@@ -311,16 +563,31 @@ describe("Test decimals", () => {
|
|
311
563
|
precision: 5,
|
312
564
|
exp: "-1.00000",
|
313
565
|
},
|
566
|
+
{
|
567
|
+
d1: new Dec(-1),
|
568
|
+
precision: 5,
|
569
|
+
exp: "-1.00000",
|
570
|
+
},
|
314
571
|
{
|
315
572
|
d1: new Dec("-7.5"),
|
316
573
|
precision: 3,
|
317
574
|
exp: "-7.500",
|
318
575
|
},
|
576
|
+
{
|
577
|
+
d1: new Dec(-7.5),
|
578
|
+
precision: 3,
|
579
|
+
exp: "-7.500",
|
580
|
+
},
|
319
581
|
{
|
320
582
|
d1: new Dec("-100.000000001"),
|
321
583
|
precision: 0,
|
322
584
|
exp: "-100",
|
323
585
|
},
|
586
|
+
{
|
587
|
+
d1: new Dec(-100.000000001),
|
588
|
+
precision: 0,
|
589
|
+
exp: "-100",
|
590
|
+
},
|
324
591
|
];
|
325
592
|
|
326
593
|
for (const test of tests) {
|
package/src/decimal.ts
CHANGED
@@ -3,17 +3,22 @@ import { Int } from "./int";
|
|
3
3
|
import { CoinUtils } from "./coin-utils";
|
4
4
|
|
5
5
|
export class Dec {
|
6
|
-
public static readonly precision
|
7
|
-
|
6
|
+
public static readonly precision = 18;
|
7
|
+
// bytes required to represent the above precision
|
8
|
+
// Ceiling[Log2[999 999 999 999 999 999]]
|
9
|
+
protected static readonly decimalPrecisionBits = 60;
|
10
|
+
protected static readonly maxDecBitLen = 256 + Dec.decimalPrecisionBits;
|
11
|
+
|
12
|
+
protected static readonly precisionMultipliers: {
|
8
13
|
[key: string]: bigInteger.BigInteger | undefined;
|
9
14
|
} = {};
|
10
|
-
|
11
|
-
prec:
|
15
|
+
protected static calcPrecisionMultiplier(
|
16
|
+
prec: number
|
12
17
|
): bigInteger.BigInteger {
|
13
|
-
if (prec
|
18
|
+
if (prec < 0) {
|
14
19
|
throw new Error("Invalid prec");
|
15
20
|
}
|
16
|
-
if (prec
|
21
|
+
if (prec > Dec.precision) {
|
17
22
|
throw new Error("Too much precision");
|
18
23
|
}
|
19
24
|
if (Dec.precisionMultipliers[prec.toString()]) {
|
@@ -21,13 +26,13 @@ export class Dec {
|
|
21
26
|
return Dec.precisionMultipliers[prec.toString()]!;
|
22
27
|
}
|
23
28
|
|
24
|
-
const zerosToAdd = Dec.precision
|
29
|
+
const zerosToAdd = Dec.precision - prec;
|
25
30
|
const multiplier = bigInteger(10).pow(zerosToAdd);
|
26
31
|
Dec.precisionMultipliers[prec.toString()] = multiplier;
|
27
32
|
return multiplier;
|
28
33
|
}
|
29
34
|
|
30
|
-
|
35
|
+
protected int: bigInteger.BigInteger;
|
31
36
|
|
32
37
|
/**
|
33
38
|
* Create a new Dec from integer with decimal place at prec
|
@@ -36,6 +41,10 @@ export class Dec {
|
|
36
41
|
* @param prec - Precision
|
37
42
|
*/
|
38
43
|
constructor(int: bigInteger.BigNumber | Int, prec: number = 0) {
|
44
|
+
if (typeof int === "number") {
|
45
|
+
int = int.toString();
|
46
|
+
}
|
47
|
+
|
39
48
|
if (typeof int === "string") {
|
40
49
|
if (int.length === 0) {
|
41
50
|
throw new Error("empty string");
|
@@ -48,8 +57,6 @@ export class Dec {
|
|
48
57
|
int = int.replace(".", "");
|
49
58
|
}
|
50
59
|
this.int = bigInteger(int);
|
51
|
-
} else if (typeof int === "number") {
|
52
|
-
this.int = bigInteger(int);
|
53
60
|
} else if (int instanceof Int) {
|
54
61
|
this.int = bigInteger(int.toString());
|
55
62
|
} else if (typeof int === "bigint") {
|
@@ -58,7 +65,15 @@ export class Dec {
|
|
58
65
|
this.int = bigInteger(int);
|
59
66
|
}
|
60
67
|
|
61
|
-
this.int = this.int.multiply(Dec.calcPrecisionMultiplier(
|
68
|
+
this.int = this.int.multiply(Dec.calcPrecisionMultiplier(prec));
|
69
|
+
|
70
|
+
this.checkBitLen();
|
71
|
+
}
|
72
|
+
|
73
|
+
protected checkBitLen(): void {
|
74
|
+
if (this.int.abs().bitLength().gt(Dec.maxDecBitLen)) {
|
75
|
+
throw new Error(`Integer out of range ${this.int.toString()}`);
|
76
|
+
}
|
62
77
|
}
|
63
78
|
|
64
79
|
public isZero(): boolean {
|
@@ -109,73 +124,80 @@ export class Dec {
|
|
109
124
|
* reverse the decimal sign.
|
110
125
|
*/
|
111
126
|
public neg(): Dec {
|
112
|
-
return new Dec(this.int.negate(), Dec.precision
|
127
|
+
return new Dec(this.int.negate(), Dec.precision);
|
113
128
|
}
|
114
129
|
|
115
130
|
/**
|
116
131
|
* Returns the absolute value of a decimals.
|
117
132
|
*/
|
118
133
|
public abs(): Dec {
|
119
|
-
return new Dec(this.int.abs(), Dec.precision
|
134
|
+
return new Dec(this.int.abs(), Dec.precision);
|
120
135
|
}
|
121
136
|
|
122
137
|
public add(d2: Dec): Dec {
|
123
|
-
return new Dec(this.int.add(d2.int), Dec.precision
|
138
|
+
return new Dec(this.int.add(d2.int), Dec.precision);
|
124
139
|
}
|
125
140
|
|
126
141
|
public sub(d2: Dec): Dec {
|
127
|
-
return new Dec(this.int.subtract(d2.int), Dec.precision
|
142
|
+
return new Dec(this.int.subtract(d2.int), Dec.precision);
|
143
|
+
}
|
144
|
+
|
145
|
+
public pow(n: Int): Dec {
|
146
|
+
if (n.isZero()) {
|
147
|
+
return new Dec(1);
|
148
|
+
}
|
149
|
+
|
150
|
+
if (n.isNegative()) {
|
151
|
+
return new Dec(1).quo(this.pow(n.abs()));
|
152
|
+
}
|
153
|
+
|
154
|
+
let base = new Dec(this.int, Dec.precision);
|
155
|
+
let tmp = new Dec(1);
|
156
|
+
|
157
|
+
for (let i = n; i.gt(new Int(1)); i = i.div(new Int(2))) {
|
158
|
+
if (!i.mod(new Int(2)).isZero()) {
|
159
|
+
tmp = tmp.mul(base);
|
160
|
+
}
|
161
|
+
base = base.mul(base);
|
162
|
+
}
|
163
|
+
|
164
|
+
return base.mul(tmp);
|
128
165
|
}
|
129
166
|
|
130
167
|
public mul(d2: Dec): Dec {
|
131
|
-
return new Dec(
|
132
|
-
this.mulRaw(d2).chopPrecisionAndRound(),
|
133
|
-
Dec.precision.toJSNumber()
|
134
|
-
);
|
168
|
+
return new Dec(this.mulRaw(d2).chopPrecisionAndRound(), Dec.precision);
|
135
169
|
}
|
136
170
|
|
137
171
|
public mulTruncate(d2: Dec): Dec {
|
138
|
-
return new Dec(
|
139
|
-
this.mulRaw(d2).chopPrecisionAndTruncate(),
|
140
|
-
Dec.precision.toJSNumber()
|
141
|
-
);
|
172
|
+
return new Dec(this.mulRaw(d2).chopPrecisionAndTruncate(), Dec.precision);
|
142
173
|
}
|
143
174
|
|
144
|
-
|
145
|
-
return new Dec(this.int.multiply(d2.int), Dec.precision
|
175
|
+
protected mulRaw(d2: Dec): Dec {
|
176
|
+
return new Dec(this.int.multiply(d2.int), Dec.precision);
|
146
177
|
}
|
147
178
|
|
148
179
|
public quo(d2: Dec): Dec {
|
149
|
-
return new Dec(
|
150
|
-
this.quoRaw(d2).chopPrecisionAndRound(),
|
151
|
-
Dec.precision.toJSNumber()
|
152
|
-
);
|
180
|
+
return new Dec(this.quoRaw(d2).chopPrecisionAndRound(), Dec.precision);
|
153
181
|
}
|
154
182
|
|
155
183
|
public quoTruncate(d2: Dec): Dec {
|
156
|
-
return new Dec(
|
157
|
-
this.quoRaw(d2).chopPrecisionAndTruncate(),
|
158
|
-
Dec.precision.toJSNumber()
|
159
|
-
);
|
184
|
+
return new Dec(this.quoRaw(d2).chopPrecisionAndTruncate(), Dec.precision);
|
160
185
|
}
|
161
186
|
|
162
187
|
public quoRoundUp(d2: Dec): Dec {
|
163
|
-
return new Dec(
|
164
|
-
this.quoRaw(d2).chopPrecisionAndRoundUp(),
|
165
|
-
Dec.precision.toJSNumber()
|
166
|
-
);
|
188
|
+
return new Dec(this.quoRaw(d2).chopPrecisionAndRoundUp(), Dec.precision);
|
167
189
|
}
|
168
190
|
|
169
|
-
|
170
|
-
const precision = Dec.calcPrecisionMultiplier(
|
191
|
+
protected quoRaw(d2: Dec): Dec {
|
192
|
+
const precision = Dec.calcPrecisionMultiplier(0);
|
171
193
|
|
172
194
|
// multiply precision twice
|
173
195
|
const mul = this.int.multiply(precision).multiply(precision);
|
174
|
-
return new Dec(mul.divide(d2.int), Dec.precision
|
196
|
+
return new Dec(mul.divide(d2.int), Dec.precision);
|
175
197
|
}
|
176
198
|
|
177
199
|
public isInteger(): boolean {
|
178
|
-
const precision = Dec.calcPrecisionMultiplier(
|
200
|
+
const precision = Dec.calcPrecisionMultiplier(0);
|
179
201
|
return this.int.remainder(precision).equals(bigInteger(0));
|
180
202
|
}
|
181
203
|
|
@@ -183,7 +205,7 @@ export class Dec {
|
|
183
205
|
* Remove a Precision amount of rightmost digits and perform bankers rounding
|
184
206
|
* on the remainder (gaussian rounding) on the digits which have been removed.
|
185
207
|
*/
|
186
|
-
|
208
|
+
protected chopPrecisionAndRound(): bigInteger.BigInteger {
|
187
209
|
// Remove the negative and add it back when returning
|
188
210
|
if (this.isNegative()) {
|
189
211
|
const absoulteDec = this.abs();
|
@@ -191,7 +213,7 @@ export class Dec {
|
|
191
213
|
return choped.negate();
|
192
214
|
}
|
193
215
|
|
194
|
-
const precision = Dec.calcPrecisionMultiplier(
|
216
|
+
const precision = Dec.calcPrecisionMultiplier(0);
|
195
217
|
const fivePrecision = precision.divide(bigInteger(2));
|
196
218
|
|
197
219
|
// Get the truncated quotient and remainder
|
@@ -216,7 +238,7 @@ export class Dec {
|
|
216
238
|
}
|
217
239
|
}
|
218
240
|
|
219
|
-
|
241
|
+
protected chopPrecisionAndRoundUp(): bigInteger.BigInteger {
|
220
242
|
// Remove the negative and add it back when returning
|
221
243
|
if (this.isNegative()) {
|
222
244
|
const absoulteDec = this.abs();
|
@@ -225,7 +247,7 @@ export class Dec {
|
|
225
247
|
return choped.negate();
|
226
248
|
}
|
227
249
|
|
228
|
-
const precision = Dec.calcPrecisionMultiplier(
|
250
|
+
const precision = Dec.calcPrecisionMultiplier(0);
|
229
251
|
|
230
252
|
// Get the truncated quotient and remainder
|
231
253
|
const { quotient, remainder } = this.int.divmod(precision);
|
@@ -241,25 +263,21 @@ export class Dec {
|
|
241
263
|
/**
|
242
264
|
* Similar to chopPrecisionAndRound, but always rounds down
|
243
265
|
*/
|
244
|
-
|
245
|
-
const precision = Dec.calcPrecisionMultiplier(
|
266
|
+
protected chopPrecisionAndTruncate(): bigInteger.BigInteger {
|
267
|
+
const precision = Dec.calcPrecisionMultiplier(0);
|
246
268
|
return this.int.divide(precision);
|
247
269
|
}
|
248
270
|
|
249
271
|
public toString(
|
250
|
-
prec: number = Dec.precision
|
272
|
+
prec: number = Dec.precision,
|
251
273
|
locale: boolean = false
|
252
274
|
): string {
|
253
|
-
const precision = Dec.calcPrecisionMultiplier(
|
275
|
+
const precision = Dec.calcPrecisionMultiplier(0);
|
254
276
|
const int = this.int.abs();
|
255
277
|
const { quotient: integer, remainder: fraction } = int.divmod(precision);
|
256
278
|
|
257
279
|
let fractionStr = fraction.toString(10);
|
258
|
-
for (
|
259
|
-
let i = 0, l = fractionStr.length;
|
260
|
-
i < Dec.precision.toJSNumber() - l;
|
261
|
-
i++
|
262
|
-
) {
|
280
|
+
for (let i = 0, l = fractionStr.length; i < Dec.precision - l; i++) {
|
263
281
|
fractionStr = "0" + fractionStr;
|
264
282
|
}
|
265
283
|
fractionStr = fractionStr.substring(0, prec);
|
@@ -290,4 +308,16 @@ export class Dec {
|
|
290
308
|
public truncate(): Int {
|
291
309
|
return new Int(this.chopPrecisionAndTruncate());
|
292
310
|
}
|
311
|
+
|
312
|
+
public roundDec(): Dec {
|
313
|
+
return new Dec(this.chopPrecisionAndRound(), 0);
|
314
|
+
}
|
315
|
+
|
316
|
+
public roundUpDec(): Dec {
|
317
|
+
return new Dec(this.chopPrecisionAndRoundUp(), 0);
|
318
|
+
}
|
319
|
+
|
320
|
+
public truncateDec(): Dec {
|
321
|
+
return new Dec(this.chopPrecisionAndTruncate(), 0);
|
322
|
+
}
|
293
323
|
}
|
package/src/index.ts
CHANGED