From 46680298c88bad12793206a32193bb0f104ce727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Fern=C3=A1ndez?= Date: Tue, 15 Sep 2020 10:06:53 +0200 Subject: [PATCH 1/3] Add Decimal.minus() implementation --- packages/math/src/decimal.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/math/src/decimal.ts b/packages/math/src/decimal.ts index ffedd0ed..0d4f1e0a 100644 --- a/packages/math/src/decimal.ts +++ b/packages/math/src/decimal.ts @@ -124,6 +124,19 @@ export class Decimal { return new Decimal(sum.toString(), this.fractionalDigits); } + /** + * a.minus(b) returns a-b. + * + * Both values need to have the same fractional digits. + * The resulting difference needs to be non-negative. + */ + public minus(b: Decimal): Decimal { + if (this.fractionalDigits !== b.fractionalDigits) throw new Error("Fractional digits do not match"); + const difference = this.data.atomics.sub(new BN(b.atomics)); + if (difference.ltn(0)) throw new Error("Difference must not be negative"); + return new Decimal(difference.toString(), this.fractionalDigits); + } + public equals(b: Decimal): boolean { return Decimal.compare(this, b) === 0; } From 0975afcb4a011b0ca3a30c988967547b1e2bc3d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Fern=C3=A1ndez?= Date: Tue, 15 Sep 2020 10:07:10 +0200 Subject: [PATCH 2/3] Add Decimal.minus() unit tests --- packages/math/src/decimal.spec.ts | 48 +++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/packages/math/src/decimal.spec.ts b/packages/math/src/decimal.spec.ts index b0e1803b..fee086e9 100644 --- a/packages/math/src/decimal.spec.ts +++ b/packages/math/src/decimal.spec.ts @@ -211,6 +211,54 @@ describe("Decimal", () => { }); }); + describe("minus", () => { + it("returns correct values", () => { + const zero = Decimal.fromUserInput("0", 5); + expect(Decimal.fromUserInput("0", 5).minus(zero).toString()).toEqual("0"); + expect(Decimal.fromUserInput("1", 5).minus(zero).toString()).toEqual("1"); + expect(Decimal.fromUserInput("2", 5).minus(zero).toString()).toEqual("2"); + expect(Decimal.fromUserInput("2.8", 5).minus(zero).toString()).toEqual("2.8"); + expect(Decimal.fromUserInput("0.12345", 5).minus(zero).toString()).toEqual("0.12345"); + + const one = Decimal.fromUserInput("1", 5); + expect(Decimal.fromUserInput("1", 5).minus(one).toString()).toEqual("0"); + expect(Decimal.fromUserInput("2", 5).minus(one).toString()).toEqual("1"); + expect(Decimal.fromUserInput("3", 5).minus(one).toString()).toEqual("2"); + expect(Decimal.fromUserInput("3.8", 5).minus(one).toString()).toEqual("2.8"); + expect(Decimal.fromUserInput("1.12345", 5).minus(one).toString()).toEqual("0.12345"); + + const oneDotFive = Decimal.fromUserInput("1.5", 5); + expect(Decimal.fromUserInput("1.5", 5).minus(oneDotFive).toString()).toEqual("0"); + expect(Decimal.fromUserInput("2.5", 5).minus(oneDotFive).toString()).toEqual("1"); + expect(Decimal.fromUserInput("3.5", 5).minus(oneDotFive).toString()).toEqual("2"); + expect(Decimal.fromUserInput("4.3", 5).minus(oneDotFive).toString()).toEqual("2.8"); + expect(Decimal.fromUserInput("1.62345", 5).minus(oneDotFive).toString()).toEqual("0.12345"); + + // original value remain unchanged + expect(zero.toString()).toEqual("0"); + expect(one.toString()).toEqual("1"); + expect(oneDotFive.toString()).toEqual("1.5"); + }); + + it("throws for different fractional digits", () => { + const zero = Decimal.fromUserInput("0", 5); + expect(() => Decimal.fromUserInput("1", 1).minus(zero)).toThrowError(/do not match/i); + expect(() => Decimal.fromUserInput("1", 2).minus(zero)).toThrowError(/do not match/i); + expect(() => Decimal.fromUserInput("1", 3).minus(zero)).toThrowError(/do not match/i); + expect(() => Decimal.fromUserInput("1", 4).minus(zero)).toThrowError(/do not match/i); + + expect(() => Decimal.fromUserInput("1", 6).minus(zero)).toThrowError(/do not match/i); + expect(() => Decimal.fromUserInput("1", 7).minus(zero)).toThrowError(/do not match/i); + }); + + it("throws for negative results", () => { + const one = Decimal.fromUserInput("1", 5); + expect(() => Decimal.fromUserInput("0", 5).minus(one)).toThrowError(/must not be negative/i); + expect(() => Decimal.fromUserInput("0.5", 5).minus(one)).toThrowError(/must not be negative/i); + expect(() => Decimal.fromUserInput("0.98765", 5).minus(one)).toThrowError(/must not be negative/i); + }); + }); + describe("equals", () => { it("returns correct values", () => { const zero = Decimal.fromUserInput("0", 5); From eeec000076c63db51a01515f7dea4a737bcf7bd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Abel=20Fern=C3=A1ndez?= Date: Tue, 15 Sep 2020 10:08:00 +0200 Subject: [PATCH 3/3] Add Decimal.minus() to declaration file --- packages/math/types/decimal.d.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/math/types/decimal.d.ts b/packages/math/types/decimal.d.ts index 0642fa07..123da718 100644 --- a/packages/math/types/decimal.d.ts +++ b/packages/math/types/decimal.d.ts @@ -24,6 +24,13 @@ export declare class Decimal { * Both values need to have the same fractional digits. */ plus(b: Decimal): Decimal; + /** + * a.minus(b) returns a-b. + * + * Both values need to have the same fractional digits. + * The resulting difference needs to be non-negative. + */ + minus(b: Decimal): Decimal; equals(b: Decimal): boolean; isLessThan(b: Decimal): boolean; isLessThanOrEqual(b: Decimal): boolean;