Skip to content

Commit

Permalink
Support minus zero
Browse files Browse the repository at this point in the history
  • Loading branch information
jessealama committed Oct 11, 2023
1 parent 2e2b545 commit 8f72f23
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 9 deletions.
15 changes: 9 additions & 6 deletions src/decimal128.mts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ const bigZero = BigInt(0);
*
* + removing any initial zeros
* + removing any trailing zeros
* + rewriting -0 to 0
* + rewriting 0.0 to 0
*
* Sign is preserved. Thus, -0.0 (e.g.) gets normalized to -0.
*
* @param s A digit string
*
* @example normalize("000123.456000") // => "123.456"
Expand All @@ -41,11 +42,7 @@ const bigZero = BigInt(0);
*/
function normalize(s: string): string {
if (s.match(/^-/)) {
let n = normalize(s.substring(1));
if ("0" === n) {
return "0";
}
return "-" + n;
return "-" + normalize(s.substring(1));
}

let a = s.replace(/^0+/, "");
Expand Down Expand Up @@ -467,6 +464,8 @@ export class Decimal128 {
BigInt((this.isNegative ? "-" : "") + this.significand + "0"),
bigOne
);
} else if (this.significand === "") {
this.rat = new Rational(0n, 1n);
} else {
this.rat = new Rational(
BigInt((this.isNegative ? "-" : "") + this.significand),
Expand All @@ -483,6 +482,10 @@ export class Decimal128 {
return "NaN";
}

if (this.isZero()) {
return (this.isNegative ? "-" : "") + "0";
}

return this.rat.toDecimalPlaces(MAX_SIGNIFICANT_DIGITS);
}

Expand Down
17 changes: 17 additions & 0 deletions tests/cmp.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,21 @@ describe("many digits", () => {
).toStrictEqual(undefined);
});
});
describe("minus zero", () => {
test("left hand", () => {
expect(new Decimal128("-0").cmp(new Decimal128("0"))).toStrictEqual(
0
);
});
test("right hand", () => {
expect(new Decimal128("0").cmp(new Decimal128("-0"))).toStrictEqual(
0
);
});
test("both arguments", () => {
expect(
new Decimal128("-0").cmp(new Decimal128("-0"))
).toStrictEqual(0);
});
});
});
6 changes: 6 additions & 0 deletions tests/constructor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ describe("constructor", () => {
).toString()
).toStrictEqual("0." + "1".repeat(MAX_SIGNIFICANT_DIGITS));
});
test("minus zero", () => {
let minusZero = new Decimal128("-0");
expect(minusZero.toString()).toStrictEqual("-0");
expect(minusZero.isNegative).toStrictEqual(true);
});
});

describe("exponential string syntax", () => {
Expand Down Expand Up @@ -225,6 +230,7 @@ describe("exponent and significand", () => {
let data = [
["123.456", "123456", -3],
["0", "", 0],
["-0", "", 0],
["0.0", "", 0],
["5", "5", 0],
["-123.456", "123456", -3],
Expand Down
20 changes: 20 additions & 0 deletions tests/negate.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Decimal128 } from "../src/decimal128.mjs";

describe("negation", () => {
test("positive number", () => {
expect(new Decimal128("123.456").negate().toString()).toStrictEqual(
"-123.456"
);
});
test("negative number", () => {
expect(new Decimal128("-123.456").negate().toString()).toStrictEqual(
"123.456"
);
});
test("zero", () => {
expect(new Decimal128("0").negate().toString()).toStrictEqual("-0");
});
test("minus zero", () => {
expect(new Decimal128("-0").negate().toString()).toStrictEqual("0");
});
});
6 changes: 3 additions & 3 deletions tests/string.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ describe("normalization", () => {
["123.0", "123"],
["00.123", "0.123"],
["0.0", "0"],
["-0.0", "0"],
["-0.0", "-0"],
["00.0", "0"],
["-00.0", "0"],
["-00.0", "-0"],
["0.00", "0"],
["-0.00", "0"],
["-0.00", "-0"],
];
for (let [a, b] of tests) {
test(`${a} is actually ${b}`, () => {
Expand Down

0 comments on commit 8f72f23

Please sign in to comment.