@keplr-wallet/unit 0.9.10 → 0.9.12-rc.0
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 +22 -9
- package/build/decimal.js +102 -29
- package/build/decimal.js.map +1 -1
- package/build/decimal.spec.js +296 -3
- package/build/decimal.spec.js.map +1 -1
- package/build/etc.d.ts +4 -0
- package/build/etc.js +66 -0
- package/build/etc.js.map +1 -0
- package/build/etc.spec.d.ts +1 -0
- package/build/etc.spec.js +66 -0
- package/build/etc.spec.js.map +1 -0
- 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 +17 -12
- package/build/int.js +69 -16
- package/build/int.js.map +1 -1
- package/build/int.spec.d.ts +1 -0
- package/build/int.spec.js +161 -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 +361 -3
- package/src/decimal.ts +135 -56
- package/src/etc.spec.ts +73 -0
- package/src/etc.ts +73 -0
- 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 +212 -0
- package/src/int.ts +94 -26
- 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/decimal.ts
CHANGED
@@ -1,19 +1,34 @@
|
|
1
1
|
import bigInteger from "big-integer";
|
2
2
|
import { Int } from "./int";
|
3
3
|
import { CoinUtils } from "./coin-utils";
|
4
|
+
import {
|
5
|
+
exponentDecStringToDecString,
|
6
|
+
isExponentDecString,
|
7
|
+
isValidDecimalString,
|
8
|
+
} from "./etc";
|
4
9
|
|
5
10
|
export class Dec {
|
6
|
-
public static readonly precision
|
7
|
-
|
11
|
+
public static readonly precision = 18;
|
12
|
+
// Bytes required to represent the above precision is 18.
|
13
|
+
// Ceiling[Log2[999 999 999 999 999 999]]
|
14
|
+
protected static readonly decimalPrecisionBits = 60;
|
15
|
+
// Max bit length for `Dec` is 256 + 60(decimalPrecisionBits)
|
16
|
+
// The int in the `Dec` is handled as integer assuming that it has 18 precision.
|
17
|
+
// (2 ** (256 + 60) - 1)
|
18
|
+
protected static readonly maxDec = bigInteger(
|
19
|
+
"133499189745056880149688856635597007162669032647290798121690100488888732861290034376435130433535"
|
20
|
+
);
|
21
|
+
|
22
|
+
protected static readonly precisionMultipliers: {
|
8
23
|
[key: string]: bigInteger.BigInteger | undefined;
|
9
24
|
} = {};
|
10
|
-
|
11
|
-
prec:
|
25
|
+
protected static calcPrecisionMultiplier(
|
26
|
+
prec: number
|
12
27
|
): bigInteger.BigInteger {
|
13
|
-
if (prec
|
28
|
+
if (prec < 0) {
|
14
29
|
throw new Error("Invalid prec");
|
15
30
|
}
|
16
|
-
if (prec
|
31
|
+
if (prec > Dec.precision) {
|
17
32
|
throw new Error("Too much precision");
|
18
33
|
}
|
19
34
|
if (Dec.precisionMultipliers[prec.toString()]) {
|
@@ -21,13 +36,39 @@ export class Dec {
|
|
21
36
|
return Dec.precisionMultipliers[prec.toString()]!;
|
22
37
|
}
|
23
38
|
|
24
|
-
const zerosToAdd = Dec.precision
|
39
|
+
const zerosToAdd = Dec.precision - prec;
|
25
40
|
const multiplier = bigInteger(10).pow(zerosToAdd);
|
26
41
|
Dec.precisionMultipliers[prec.toString()] = multiplier;
|
27
42
|
return multiplier;
|
28
43
|
}
|
29
44
|
|
30
|
-
|
45
|
+
protected static reduceDecimalsFromString(
|
46
|
+
str: string
|
47
|
+
): { res: string; isDownToZero: boolean } {
|
48
|
+
const decimalPointIndex = str.indexOf(".");
|
49
|
+
if (decimalPointIndex < 0) {
|
50
|
+
return {
|
51
|
+
res: str,
|
52
|
+
isDownToZero: false,
|
53
|
+
};
|
54
|
+
}
|
55
|
+
|
56
|
+
const exceededDecimals = str.length - 1 - decimalPointIndex - Dec.precision;
|
57
|
+
if (exceededDecimals <= 0) {
|
58
|
+
return {
|
59
|
+
res: str,
|
60
|
+
isDownToZero: false,
|
61
|
+
};
|
62
|
+
}
|
63
|
+
|
64
|
+
const res = str.slice(0, str.length - exceededDecimals);
|
65
|
+
return {
|
66
|
+
res,
|
67
|
+
isDownToZero: /^[0.]*$/.test(res),
|
68
|
+
};
|
69
|
+
}
|
70
|
+
|
71
|
+
protected int: bigInteger.BigInteger;
|
31
72
|
|
32
73
|
/**
|
33
74
|
* Create a new Dec from integer with decimal place at prec
|
@@ -36,20 +77,35 @@ export class Dec {
|
|
36
77
|
* @param prec - Precision
|
37
78
|
*/
|
38
79
|
constructor(int: bigInteger.BigNumber | Int, prec: number = 0) {
|
80
|
+
if (typeof int === "number") {
|
81
|
+
int = int.toString();
|
82
|
+
}
|
83
|
+
|
39
84
|
if (typeof int === "string") {
|
40
85
|
if (int.length === 0) {
|
41
86
|
throw new Error("empty string");
|
42
87
|
}
|
43
|
-
if (
|
44
|
-
|
88
|
+
if (!isValidDecimalString(int)) {
|
89
|
+
if (isExponentDecString(int)) {
|
90
|
+
int = exponentDecStringToDecString(int);
|
91
|
+
} else {
|
92
|
+
throw new Error(`invalid decimal: ${int}`);
|
93
|
+
}
|
45
94
|
}
|
95
|
+
// Even if an input with more than 18 decimals, it does not throw an error and ignores the rest.
|
96
|
+
const reduced = Dec.reduceDecimalsFromString(int);
|
97
|
+
if (reduced.isDownToZero) {
|
98
|
+
// However, as a result, if the input becomes 0, a problem may occur in mul or quo. In this case, print a warning.
|
99
|
+
console.log(
|
100
|
+
`WARNING: Got ${int}. Dec can only handle up to 18 decimals. However, since the decimal point of the input exceeds 18 digits, the remainder is discarded. As a result, input becomes 0.`
|
101
|
+
);
|
102
|
+
}
|
103
|
+
int = reduced.res;
|
46
104
|
if (int.indexOf(".") >= 0) {
|
47
105
|
prec = int.length - int.indexOf(".") - 1;
|
48
106
|
int = int.replace(".", "");
|
49
107
|
}
|
50
108
|
this.int = bigInteger(int);
|
51
|
-
} else if (typeof int === "number") {
|
52
|
-
this.int = bigInteger(int);
|
53
109
|
} else if (int instanceof Int) {
|
54
110
|
this.int = bigInteger(int.toString());
|
55
111
|
} else if (typeof int === "bigint") {
|
@@ -58,7 +114,15 @@ export class Dec {
|
|
58
114
|
this.int = bigInteger(int);
|
59
115
|
}
|
60
116
|
|
61
|
-
this.int = this.int.multiply(Dec.calcPrecisionMultiplier(
|
117
|
+
this.int = this.int.multiply(Dec.calcPrecisionMultiplier(prec));
|
118
|
+
|
119
|
+
this.checkBitLen();
|
120
|
+
}
|
121
|
+
|
122
|
+
protected checkBitLen(): void {
|
123
|
+
if (this.int.abs().gt(Dec.maxDec)) {
|
124
|
+
throw new Error(`Integer out of range ${this.int.toString()}`);
|
125
|
+
}
|
62
126
|
}
|
63
127
|
|
64
128
|
public isZero(): boolean {
|
@@ -109,73 +173,80 @@ export class Dec {
|
|
109
173
|
* reverse the decimal sign.
|
110
174
|
*/
|
111
175
|
public neg(): Dec {
|
112
|
-
return new Dec(this.int.negate(), Dec.precision
|
176
|
+
return new Dec(this.int.negate(), Dec.precision);
|
113
177
|
}
|
114
178
|
|
115
179
|
/**
|
116
180
|
* Returns the absolute value of a decimals.
|
117
181
|
*/
|
118
182
|
public abs(): Dec {
|
119
|
-
return new Dec(this.int.abs(), Dec.precision
|
183
|
+
return new Dec(this.int.abs(), Dec.precision);
|
120
184
|
}
|
121
185
|
|
122
186
|
public add(d2: Dec): Dec {
|
123
|
-
return new Dec(this.int.add(d2.int), Dec.precision
|
187
|
+
return new Dec(this.int.add(d2.int), Dec.precision);
|
124
188
|
}
|
125
189
|
|
126
190
|
public sub(d2: Dec): Dec {
|
127
|
-
return new Dec(this.int.subtract(d2.int), Dec.precision
|
191
|
+
return new Dec(this.int.subtract(d2.int), Dec.precision);
|
192
|
+
}
|
193
|
+
|
194
|
+
public pow(n: Int): Dec {
|
195
|
+
if (n.isZero()) {
|
196
|
+
return new Dec(1);
|
197
|
+
}
|
198
|
+
|
199
|
+
if (n.isNegative()) {
|
200
|
+
return new Dec(1).quo(this.pow(n.abs()));
|
201
|
+
}
|
202
|
+
|
203
|
+
let base = new Dec(this.int, Dec.precision);
|
204
|
+
let tmp = new Dec(1);
|
205
|
+
|
206
|
+
for (let i = n; i.gt(new Int(1)); i = i.div(new Int(2))) {
|
207
|
+
if (!i.mod(new Int(2)).isZero()) {
|
208
|
+
tmp = tmp.mul(base);
|
209
|
+
}
|
210
|
+
base = base.mul(base);
|
211
|
+
}
|
212
|
+
|
213
|
+
return base.mul(tmp);
|
128
214
|
}
|
129
215
|
|
130
216
|
public mul(d2: Dec): Dec {
|
131
|
-
return new Dec(
|
132
|
-
this.mulRaw(d2).chopPrecisionAndRound(),
|
133
|
-
Dec.precision.toJSNumber()
|
134
|
-
);
|
217
|
+
return new Dec(this.mulRaw(d2).chopPrecisionAndRound(), Dec.precision);
|
135
218
|
}
|
136
219
|
|
137
220
|
public mulTruncate(d2: Dec): Dec {
|
138
|
-
return new Dec(
|
139
|
-
this.mulRaw(d2).chopPrecisionAndTruncate(),
|
140
|
-
Dec.precision.toJSNumber()
|
141
|
-
);
|
221
|
+
return new Dec(this.mulRaw(d2).chopPrecisionAndTruncate(), Dec.precision);
|
142
222
|
}
|
143
223
|
|
144
|
-
|
145
|
-
return new Dec(this.int.multiply(d2.int), Dec.precision
|
224
|
+
protected mulRaw(d2: Dec): Dec {
|
225
|
+
return new Dec(this.int.multiply(d2.int), Dec.precision);
|
146
226
|
}
|
147
227
|
|
148
228
|
public quo(d2: Dec): Dec {
|
149
|
-
return new Dec(
|
150
|
-
this.quoRaw(d2).chopPrecisionAndRound(),
|
151
|
-
Dec.precision.toJSNumber()
|
152
|
-
);
|
229
|
+
return new Dec(this.quoRaw(d2).chopPrecisionAndRound(), Dec.precision);
|
153
230
|
}
|
154
231
|
|
155
232
|
public quoTruncate(d2: Dec): Dec {
|
156
|
-
return new Dec(
|
157
|
-
this.quoRaw(d2).chopPrecisionAndTruncate(),
|
158
|
-
Dec.precision.toJSNumber()
|
159
|
-
);
|
233
|
+
return new Dec(this.quoRaw(d2).chopPrecisionAndTruncate(), Dec.precision);
|
160
234
|
}
|
161
235
|
|
162
236
|
public quoRoundUp(d2: Dec): Dec {
|
163
|
-
return new Dec(
|
164
|
-
this.quoRaw(d2).chopPrecisionAndRoundUp(),
|
165
|
-
Dec.precision.toJSNumber()
|
166
|
-
);
|
237
|
+
return new Dec(this.quoRaw(d2).chopPrecisionAndRoundUp(), Dec.precision);
|
167
238
|
}
|
168
239
|
|
169
|
-
|
170
|
-
const precision = Dec.calcPrecisionMultiplier(
|
240
|
+
protected quoRaw(d2: Dec): Dec {
|
241
|
+
const precision = Dec.calcPrecisionMultiplier(0);
|
171
242
|
|
172
243
|
// multiply precision twice
|
173
244
|
const mul = this.int.multiply(precision).multiply(precision);
|
174
|
-
return new Dec(mul.divide(d2.int), Dec.precision
|
245
|
+
return new Dec(mul.divide(d2.int), Dec.precision);
|
175
246
|
}
|
176
247
|
|
177
248
|
public isInteger(): boolean {
|
178
|
-
const precision = Dec.calcPrecisionMultiplier(
|
249
|
+
const precision = Dec.calcPrecisionMultiplier(0);
|
179
250
|
return this.int.remainder(precision).equals(bigInteger(0));
|
180
251
|
}
|
181
252
|
|
@@ -183,7 +254,7 @@ export class Dec {
|
|
183
254
|
* Remove a Precision amount of rightmost digits and perform bankers rounding
|
184
255
|
* on the remainder (gaussian rounding) on the digits which have been removed.
|
185
256
|
*/
|
186
|
-
|
257
|
+
protected chopPrecisionAndRound(): bigInteger.BigInteger {
|
187
258
|
// Remove the negative and add it back when returning
|
188
259
|
if (this.isNegative()) {
|
189
260
|
const absoulteDec = this.abs();
|
@@ -191,7 +262,7 @@ export class Dec {
|
|
191
262
|
return choped.negate();
|
192
263
|
}
|
193
264
|
|
194
|
-
const precision = Dec.calcPrecisionMultiplier(
|
265
|
+
const precision = Dec.calcPrecisionMultiplier(0);
|
195
266
|
const fivePrecision = precision.divide(bigInteger(2));
|
196
267
|
|
197
268
|
// Get the truncated quotient and remainder
|
@@ -216,7 +287,7 @@ export class Dec {
|
|
216
287
|
}
|
217
288
|
}
|
218
289
|
|
219
|
-
|
290
|
+
protected chopPrecisionAndRoundUp(): bigInteger.BigInteger {
|
220
291
|
// Remove the negative and add it back when returning
|
221
292
|
if (this.isNegative()) {
|
222
293
|
const absoulteDec = this.abs();
|
@@ -225,7 +296,7 @@ export class Dec {
|
|
225
296
|
return choped.negate();
|
226
297
|
}
|
227
298
|
|
228
|
-
const precision = Dec.calcPrecisionMultiplier(
|
299
|
+
const precision = Dec.calcPrecisionMultiplier(0);
|
229
300
|
|
230
301
|
// Get the truncated quotient and remainder
|
231
302
|
const { quotient, remainder } = this.int.divmod(precision);
|
@@ -241,25 +312,21 @@ export class Dec {
|
|
241
312
|
/**
|
242
313
|
* Similar to chopPrecisionAndRound, but always rounds down
|
243
314
|
*/
|
244
|
-
|
245
|
-
const precision = Dec.calcPrecisionMultiplier(
|
315
|
+
protected chopPrecisionAndTruncate(): bigInteger.BigInteger {
|
316
|
+
const precision = Dec.calcPrecisionMultiplier(0);
|
246
317
|
return this.int.divide(precision);
|
247
318
|
}
|
248
319
|
|
249
320
|
public toString(
|
250
|
-
prec: number = Dec.precision
|
321
|
+
prec: number = Dec.precision,
|
251
322
|
locale: boolean = false
|
252
323
|
): string {
|
253
|
-
const precision = Dec.calcPrecisionMultiplier(
|
324
|
+
const precision = Dec.calcPrecisionMultiplier(0);
|
254
325
|
const int = this.int.abs();
|
255
326
|
const { quotient: integer, remainder: fraction } = int.divmod(precision);
|
256
327
|
|
257
328
|
let fractionStr = fraction.toString(10);
|
258
|
-
for (
|
259
|
-
let i = 0, l = fractionStr.length;
|
260
|
-
i < Dec.precision.toJSNumber() - l;
|
261
|
-
i++
|
262
|
-
) {
|
329
|
+
for (let i = 0, l = fractionStr.length; i < Dec.precision - l; i++) {
|
263
330
|
fractionStr = "0" + fractionStr;
|
264
331
|
}
|
265
332
|
fractionStr = fractionStr.substring(0, prec);
|
@@ -290,4 +357,16 @@ export class Dec {
|
|
290
357
|
public truncate(): Int {
|
291
358
|
return new Int(this.chopPrecisionAndTruncate());
|
292
359
|
}
|
360
|
+
|
361
|
+
public roundDec(): Dec {
|
362
|
+
return new Dec(this.chopPrecisionAndRound(), 0);
|
363
|
+
}
|
364
|
+
|
365
|
+
public roundUpDec(): Dec {
|
366
|
+
return new Dec(this.chopPrecisionAndRoundUp(), 0);
|
367
|
+
}
|
368
|
+
|
369
|
+
public truncateDec(): Dec {
|
370
|
+
return new Dec(this.chopPrecisionAndTruncate(), 0);
|
371
|
+
}
|
293
372
|
}
|
package/src/etc.spec.ts
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
import { exponentDecStringToDecString } from "./etc";
|
2
|
+
|
3
|
+
describe("Test etc utils", () => {
|
4
|
+
it("Test exponentDecStringToDecString", () => {
|
5
|
+
expect(exponentDecStringToDecString("1e+0")).toBe("1");
|
6
|
+
expect(exponentDecStringToDecString("1e+1")).toBe("10");
|
7
|
+
expect(exponentDecStringToDecString("123e+1")).toBe("1230");
|
8
|
+
expect(exponentDecStringToDecString("123e+2")).toBe("12300");
|
9
|
+
expect(exponentDecStringToDecString("123e+3")).toBe("123000");
|
10
|
+
expect(exponentDecStringToDecString("123e+4")).toBe("1230000");
|
11
|
+
|
12
|
+
expect(exponentDecStringToDecString("-1e+0")).toBe("-1");
|
13
|
+
expect(exponentDecStringToDecString("-1e+1")).toBe("-10");
|
14
|
+
expect(exponentDecStringToDecString("-123e+1")).toBe("-1230");
|
15
|
+
expect(exponentDecStringToDecString("-123e+2")).toBe("-12300");
|
16
|
+
expect(exponentDecStringToDecString("-123e+3")).toBe("-123000");
|
17
|
+
expect(exponentDecStringToDecString("-123e+4")).toBe("-1230000");
|
18
|
+
|
19
|
+
expect(exponentDecStringToDecString("1.2e+0")).toBe("1.2");
|
20
|
+
expect(exponentDecStringToDecString("1.2e+1")).toBe("12");
|
21
|
+
expect(exponentDecStringToDecString("1.23e+1")).toBe("12.3");
|
22
|
+
expect(exponentDecStringToDecString("1.23e+2")).toBe("123");
|
23
|
+
expect(exponentDecStringToDecString("1.23e+3")).toBe("1230");
|
24
|
+
expect(exponentDecStringToDecString("1.23e+4")).toBe("12300");
|
25
|
+
|
26
|
+
expect(exponentDecStringToDecString("-1.2e+0")).toBe("-1.2");
|
27
|
+
expect(exponentDecStringToDecString("-1.2e+1")).toBe("-12");
|
28
|
+
expect(exponentDecStringToDecString("-1.23e+1")).toBe("-12.3");
|
29
|
+
expect(exponentDecStringToDecString("-1.23e+2")).toBe("-123");
|
30
|
+
expect(exponentDecStringToDecString("-1.23e+3")).toBe("-1230");
|
31
|
+
expect(exponentDecStringToDecString("-1.23e+4")).toBe("-12300");
|
32
|
+
|
33
|
+
expect(exponentDecStringToDecString("1e-0")).toBe("1");
|
34
|
+
expect(exponentDecStringToDecString("1e-1")).toBe("0.1");
|
35
|
+
expect(exponentDecStringToDecString("123e-1")).toBe("12.3");
|
36
|
+
expect(exponentDecStringToDecString("123e-2")).toBe("1.23");
|
37
|
+
expect(exponentDecStringToDecString("123e-3")).toBe("0.123");
|
38
|
+
expect(exponentDecStringToDecString("123e-4")).toBe("0.0123");
|
39
|
+
|
40
|
+
expect(exponentDecStringToDecString("-1e-0")).toBe("-1");
|
41
|
+
expect(exponentDecStringToDecString("-1e-1")).toBe("-0.1");
|
42
|
+
expect(exponentDecStringToDecString("-123e-1")).toBe("-12.3");
|
43
|
+
expect(exponentDecStringToDecString("-123e-2")).toBe("-1.23");
|
44
|
+
expect(exponentDecStringToDecString("-123e-3")).toBe("-0.123");
|
45
|
+
expect(exponentDecStringToDecString("-123e-4")).toBe("-0.0123");
|
46
|
+
|
47
|
+
expect(exponentDecStringToDecString("1.2e-0")).toBe("1.2");
|
48
|
+
expect(exponentDecStringToDecString("1.2e-1")).toBe("0.12");
|
49
|
+
expect(exponentDecStringToDecString("1.23e-1")).toBe("0.123");
|
50
|
+
expect(exponentDecStringToDecString("1.23e-2")).toBe("0.0123");
|
51
|
+
expect(exponentDecStringToDecString("1.23e-3")).toBe("0.00123");
|
52
|
+
expect(exponentDecStringToDecString("1.23e-4")).toBe("0.000123");
|
53
|
+
|
54
|
+
expect(exponentDecStringToDecString("-1.2e-0")).toBe("-1.2");
|
55
|
+
expect(exponentDecStringToDecString("-1.2e-1")).toBe("-0.12");
|
56
|
+
expect(exponentDecStringToDecString("-1.23e-1")).toBe("-0.123");
|
57
|
+
expect(exponentDecStringToDecString("-1.23e-2")).toBe("-0.0123");
|
58
|
+
expect(exponentDecStringToDecString("-1.23e-3")).toBe("-0.00123");
|
59
|
+
expect(exponentDecStringToDecString("-1.23e-4")).toBe("-0.000123");
|
60
|
+
|
61
|
+
expect(exponentDecStringToDecString("0.00123e+1")).toBe("0.0123");
|
62
|
+
expect(exponentDecStringToDecString("0.00123e-1")).toBe("0.000123");
|
63
|
+
expect(exponentDecStringToDecString("0.00123e+4")).toBe("12.3");
|
64
|
+
expect(exponentDecStringToDecString("0.00123e-4")).toBe("0.000000123");
|
65
|
+
expect(exponentDecStringToDecString("1234.567e+2")).toBe("123456.7");
|
66
|
+
expect(exponentDecStringToDecString("1234.567e+3")).toBe("1234567");
|
67
|
+
expect(exponentDecStringToDecString("1234.567e+4")).toBe("12345670");
|
68
|
+
expect(exponentDecStringToDecString("1234.567e+10")).toBe("12345670000000");
|
69
|
+
|
70
|
+
expect(exponentDecStringToDecString("-0.00123e+1")).toBe("-0.0123");
|
71
|
+
expect(exponentDecStringToDecString("-0.00123e-1")).toBe("-0.000123");
|
72
|
+
});
|
73
|
+
});
|
package/src/etc.ts
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
const regexIntString = /^-?\d+$/;
|
2
|
+
const regexDecString = /^-?\d+.?\d*$/;
|
3
|
+
const regexExponentDecString = /^(-?)([\d.]+)e([-+])([\d]+)$/;
|
4
|
+
|
5
|
+
export function isValidIntegerString(str: string): boolean {
|
6
|
+
return regexIntString.test(str);
|
7
|
+
}
|
8
|
+
|
9
|
+
export function isValidDecimalString(str: string): boolean {
|
10
|
+
return regexDecString.test(str);
|
11
|
+
}
|
12
|
+
|
13
|
+
export function isExponentDecString(str: string): boolean {
|
14
|
+
return regexExponentDecString.test(str);
|
15
|
+
}
|
16
|
+
|
17
|
+
function makeZerosStr(len: number): string {
|
18
|
+
let r = "";
|
19
|
+
for (let i = 0; i < len; i++) {
|
20
|
+
r += "0";
|
21
|
+
}
|
22
|
+
return r;
|
23
|
+
}
|
24
|
+
|
25
|
+
function removeHeadZeros(str: string): string {
|
26
|
+
while (str.length > 0 && str[0] === "0") {
|
27
|
+
str = str.slice(1);
|
28
|
+
}
|
29
|
+
if (str.length === 0 || str[0] === ".") {
|
30
|
+
return "0" + str;
|
31
|
+
}
|
32
|
+
return str;
|
33
|
+
}
|
34
|
+
|
35
|
+
export function exponentDecStringToDecString(str: string): string {
|
36
|
+
const split = str.split(regexExponentDecString);
|
37
|
+
if (split.length !== 6) {
|
38
|
+
return str;
|
39
|
+
}
|
40
|
+
|
41
|
+
const isNeg = split[1] === "-";
|
42
|
+
let numStr = split[2];
|
43
|
+
const numStrFractionIndex = numStr.indexOf(".");
|
44
|
+
|
45
|
+
const exponentStr = split[4];
|
46
|
+
let exponent = parseInt(exponentStr) * (split[3] === "-" ? -1 : 1);
|
47
|
+
|
48
|
+
if (numStrFractionIndex >= 0) {
|
49
|
+
const fractionLen = numStr.length - numStrFractionIndex - 1;
|
50
|
+
exponent = exponent - fractionLen;
|
51
|
+
|
52
|
+
numStr = removeHeadZeros(numStr.replace(".", ""));
|
53
|
+
}
|
54
|
+
|
55
|
+
const prefix = isNeg ? "-" : "";
|
56
|
+
|
57
|
+
if (exponent < 0) {
|
58
|
+
if (numStr.length > -exponent) {
|
59
|
+
const fractionPosition = numStr.length + exponent;
|
60
|
+
|
61
|
+
return (
|
62
|
+
prefix +
|
63
|
+
(numStr.slice(0, fractionPosition) +
|
64
|
+
"." +
|
65
|
+
numStr.slice(fractionPosition))
|
66
|
+
);
|
67
|
+
}
|
68
|
+
|
69
|
+
return prefix + "0." + makeZerosStr(-(numStr.length + exponent)) + numStr;
|
70
|
+
} else {
|
71
|
+
return prefix + numStr + makeZerosStr(exponent);
|
72
|
+
}
|
73
|
+
}
|
package/src/index.ts
CHANGED