Skip to content
This repository was archived by the owner on Jan 15, 2025. It is now read-only.

Commit 6260eb2

Browse files
authored
Add more serialization methods (#110)
* Require tsx * Add a currency conversion example * Run examples with `tsx` * Add some examples * Ensure rounding * Add tests for `toPrecision` and `toExponential`
1 parent 2831199 commit 6260eb2

17 files changed

+1350
-52
lines changed

.github/workflows/push.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ jobs:
3030
- name: check coverage
3131
run: npx c8 check-coverage --lines 99 --functions 99 --branches 99 --statements 99
3232
- name: examples do not crash
33-
run: for f in examples/*.js; do node $f || (echo "'$f' crashed"; exit 1); done
33+
run: for f in examples/*.ts; do npx tsx "$f" || (echo "'$f' crashed"; exit 1); done

examples/currency.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Decimal128 } from "../src/decimal128.mjs";
2+
3+
let exchangeRateEurToUsd = new Decimal128("1.09");
4+
let amountInUsd = new Decimal128("450.27");
5+
let exchangeRateUsdToEur = new Decimal128(1).divide(exchangeRateEurToUsd);
6+
7+
let amountInEur = exchangeRateUsdToEur.multiply(amountInUsd);
8+
console.log(amountInEur.round(2).toString());

examples/five-numbers.ts

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { Decimal128 } from "../src/decimal128.mjs";
2+
3+
function getRandomInt(max: number): number {
4+
return Math.floor(Math.random() * max);
5+
}
6+
7+
function getRandomDigits(n: number): number[] {
8+
let digits = [];
9+
for (let i = 0; i < n; i++) {
10+
digits.push(getRandomInt(10));
11+
}
12+
return digits;
13+
}
14+
15+
function getRandomDigitsAsString(n: number): string {
16+
let digits = getRandomDigits(n + 4);
17+
return digits.slice(0, n).join("") + "." + digits.slice(n).join("");
18+
}
19+
20+
function compareNumbers(
21+
digits1: string,
22+
digits2: string,
23+
digits3: string,
24+
digits4: string,
25+
digits5: string
26+
): [string, string] {
27+
let d1 = new Decimal128(digits1);
28+
let d2 = new Decimal128(digits2);
29+
let d3 = new Decimal128(digits3);
30+
let d4 = new Decimal128(digits4);
31+
let d5 = new Decimal128(digits5);
32+
33+
let decimalResult = d1.add(d2).add(d3).add(d4).multiply(d5);
34+
let numberResult =
35+
(Number(digits1) +
36+
Number(digits2) +
37+
Number(digits3) +
38+
Number(digits4)) *
39+
Number(digits5);
40+
let numberResultString = numberResult.toFixed(4);
41+
let decimalResultString = decimalResult.toFixed(4);
42+
43+
return [numberResultString, decimalResultString];
44+
}
45+
46+
function keepTrying(): boolean {
47+
let digits1 = getRandomDigitsAsString(3);
48+
let digits2 = getRandomDigitsAsString(3);
49+
let digits3 = getRandomDigitsAsString(4);
50+
let digits4 = getRandomDigitsAsString(4);
51+
let digits5 = getRandomDigitsAsString(4);
52+
53+
let [result1, result2] = compareNumbers(
54+
digits1,
55+
digits2,
56+
digits3,
57+
digits4,
58+
digits5
59+
);
60+
61+
if (result1 !== result2) {
62+
let diff = new Decimal128(result1)
63+
.subtract(new Decimal128(result2))
64+
.abs();
65+
console.log(
66+
`(${digits1} + ${digits2} + ${digits3} + ${digits4}) * ${digits5} = ${result1} but it should be ${result2} (difference: ${diff.toString()})`
67+
);
68+
}
69+
70+
return result1 !== result2;
71+
}
72+
73+
let numAttempts = 1000;
74+
let numFailures = 0;
75+
for (let i = 0; i < numAttempts; i++) {
76+
let failed = keepTrying();
77+
if (failed) {
78+
numFailures++;
79+
}
80+
}
81+
82+
console.log(`Failed ${numFailures} out of ${numAttempts} attempts`);

examples/midprice.ts

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { Decimal128 } from "../src/decimal128.mjs";
2+
3+
function getRandomInt(max: number): number {
4+
return Math.floor(Math.random() * max);
5+
}
6+
7+
function getRandomDigits(n: number): number[] {
8+
let digits = [];
9+
for (let i = 0; i < n; i++) {
10+
digits.push(getRandomInt(10));
11+
}
12+
return digits;
13+
}
14+
15+
function getRandomDigitsAsString(n: number): string {
16+
let digits = getRandomDigits(n + 4);
17+
return digits.slice(0, n).join("") + "." + digits.slice(n).join("");
18+
}
19+
20+
const two = new Decimal128(2);
21+
22+
function compareNumbers(digits1: string, digits2: string): [string, string] {
23+
let d1 = new Decimal128(digits1);
24+
let d2 = new Decimal128(digits2);
25+
26+
let decimalResult = d1.add(d2).divide(two);
27+
let numberResult = (Number(digits1) + Number(digits2)) / 2;
28+
let numberResultString = numberResult.toFixed(4);
29+
let decimalResultString = decimalResult.toFixed(4);
30+
31+
return [numberResultString, decimalResultString];
32+
}
33+
34+
function keepTrying(): boolean {
35+
let digits1 = getRandomDigitsAsString(3);
36+
let digits2 = getRandomDigitsAsString(3);
37+
let [result1, result2] = compareNumbers(digits1, digits2);
38+
39+
if (result1 !== result2) {
40+
let diff = new Decimal128(result1)
41+
.subtract(new Decimal128(result2))
42+
.abs();
43+
console.log(
44+
`(${digits1} + ${digits2})/2 = ${result1} but it should be ${result2} (difference: ${diff.toString()})`
45+
);
46+
}
47+
48+
return result1 !== result2;
49+
}
50+
51+
let numAttempts = 1000;
52+
let numFailures = 0;
53+
for (let i = 0; i < numAttempts; i++) {
54+
let failed = keepTrying();
55+
if (failed) {
56+
numFailures++;
57+
}
58+
}
59+
60+
console.log(`Failed ${numFailures} out of ${numAttempts} attempts`);

examples/rounding-error.ts

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { Decimal128 } from "../src/decimal128.mjs";
2+
3+
function getRandomInt(max: number): number {
4+
return Math.floor(Math.random() * max);
5+
}
6+
7+
function getRandomDigits(n: number): number[] {
8+
let digits = [];
9+
for (let i = 0; i < n; i++) {
10+
digits.push(getRandomInt(10));
11+
}
12+
return digits;
13+
}
14+
15+
function getRandomDigitsAsString(n: number): string {
16+
let digits = getRandomDigits(n + 4);
17+
return digits.slice(0, n).join("") + "." + digits.slice(n).join("");
18+
}
19+
20+
function compareNumbers(
21+
digits1: string,
22+
digits2: string,
23+
digits3: string
24+
): [string, string] {
25+
let d1 = new Decimal128(digits1);
26+
let d2 = new Decimal128(digits2);
27+
let d3 = new Decimal128(digits3);
28+
29+
let decimalResult = d1.multiply(d2).add(d3);
30+
let numberResult = Number(digits1) * Number(digits2) + Number(digits3);
31+
let numberResultString = numberResult.toFixed(4);
32+
let decimalResultString = decimalResult.toFixed(4);
33+
34+
return [numberResultString, decimalResultString];
35+
}
36+
37+
function keepTrying(): boolean {
38+
let digits1 = getRandomDigitsAsString(5);
39+
let digits2 = getRandomDigitsAsString(3);
40+
let digits3 = getRandomDigitsAsString(4);
41+
let [result1, result2] = compareNumbers(digits1, digits2, digits3);
42+
43+
if (result1 !== result2) {
44+
let diff = new Decimal128(result1)
45+
.subtract(new Decimal128(result2))
46+
.abs();
47+
console.log(
48+
`(${digits1} * ${digits2}) + ${digits3} = ${result1} but it should be ${result2} (difference of ${diff.toString()})`
49+
);
50+
}
51+
52+
return result1 !== result2;
53+
}
54+
55+
let numAttempts = 1000;
56+
let numFailures = 0;
57+
for (let i = 0; i < numAttempts; i++) {
58+
let failed = keepTrying();
59+
if (failed) {
60+
numFailures++;
61+
}
62+
}
63+
64+
console.log(`Failed ${numFailures} out of ${numAttempts} attempts`);

examples/roundtrip.ts

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { Decimal128 } from "../src/decimal128.mjs";
2+
3+
function getRandomInt(max: number): number {
4+
return Math.floor(Math.random() * max);
5+
}
6+
7+
function getRandomDigits(n: number): number[] {
8+
let digits = [];
9+
for (let i = 0; i < n; i++) {
10+
digits.push(getRandomInt(10));
11+
}
12+
return digits;
13+
}
14+
15+
function getRandomDigitsAsString(n: number): string {
16+
let digits = getRandomDigits(n + 2);
17+
let result = digits.slice(0, n).join("") + "." + digits.slice(n).join("");
18+
let noInitialZeroes = result.replace(/^0+/, "");
19+
let noTrailingZeroes = noInitialZeroes.replace(/0+$/, "");
20+
return noTrailingZeroes.replace(/\.$/, "");
21+
}
22+
23+
function compareNumbers(digits1: string): string {
24+
return Number(digits1).toString();
25+
}
26+
27+
function keepTrying(): boolean {
28+
let digits1 = getRandomDigitsAsString(9);
29+
let result1 = compareNumbers(digits1);
30+
31+
if (digits1 !== result1) {
32+
console.log(`${digits1} != ${result1}`);
33+
}
34+
35+
return digits1 !== result1;
36+
}
37+
38+
let numAttempts = 1000;
39+
let numFailures = 0;
40+
for (let i = 0; i < numAttempts; i++) {
41+
let failed = keepTrying();
42+
if (failed) {
43+
numFailures++;
44+
}
45+
}
46+
47+
console.log(`Failed ${numFailures} out of ${numAttempts} attempts`);

0 commit comments

Comments
 (0)