From b305d2611f7256fdd0608f945c7b0984151e064c Mon Sep 17 00:00:00 2001 From: Evert Pot Date: Sat, 1 Aug 2020 16:42:08 -0400 Subject: [PATCH 1/4] POW operation. This is a first slow version. Lets see if we can speed this up. Fixes #35 --- .eslintrc.json | 5 +++-- src/money.ts | 31 +++++++++++++++++++++++++++++++ test/money.ts | 25 +++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index a3ccd87..a3d3ea1 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -45,6 +45,7 @@ "ts-expect-error": "allow-with-description" } ], - "@typescript-eslint/no-explicit-any" : 0 + "@typescript-eslint/no-explicit-any" : 0, + "@typescript-eslint/no-this-alias": 0 } -} \ No newline at end of file +} diff --git a/src/money.ts b/src/money.ts index 44d36cd..e6b4844 100644 --- a/src/money.ts +++ b/src/money.ts @@ -110,6 +110,37 @@ export class Money { } + /** + * Pow returns the current value to it's exponent. + * + * pow currently only supports whole numbers. + */ + pow(exponent: number): Money { + + if (!Number.isInteger(exponent)) { + throw new Error('You can currently only use pow() with whole numbers'); + } + + if (exponent===1) { + return this; + } else if (exponent === 0) { + return new Money(1, this.currency); + } else if (exponent > 1) { + let base:Money = this; + for(let i = 1; i < exponent; i++) { + base = base.multiply(this); + } + return base; + } else { + let base:Money = this; + for(let i = 1; i > exponent; i--) { + base = base.divide(this); + } + return base; + } + + } + /** * Returns the absolute value. */ diff --git a/test/money.ts b/test/money.ts index 797a696..1577e65 100644 --- a/test/money.ts +++ b/test/money.ts @@ -287,6 +287,31 @@ describe('Money class', () => { }); + describe('pow', () => { + + const cases: [string|number, number, string][] = [ + ['1', 5,'1.00'], + ['2', 8, '256.00'], + [5, 3, '125.00'], + [-10, 5, '-100000.00'], + [-10, 1, '-10.00'], + [-10, 0, '1.00'], + [2, -2, '0.25'], + ]; + + for (const cas of cases) { + + it(`${cas[0]} ** ${cas[1]} = ${cas[2]}`, () => { + + const x = new Money(cas[0], 'CAD'); + expect(x.pow(cas[1]).toFixed(2)).to.equal(cas[2]); + + }); + + } + + }); + describe('abs', () => { const cases = [ From edb713903af4eb1234e77dc3051f4f5c1d7992b9 Mon Sep 17 00:00:00 2001 From: Evert Pot Date: Sat, 1 Aug 2020 16:44:37 -0400 Subject: [PATCH 2/4] Remove redundant branches --- src/money.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/money.ts b/src/money.ts index e6b4844..a4cbc1a 100644 --- a/src/money.ts +++ b/src/money.ts @@ -121,11 +121,7 @@ export class Money { throw new Error('You can currently only use pow() with whole numbers'); } - if (exponent===1) { - return this; - } else if (exponent === 0) { - return new Money(1, this.currency); - } else if (exponent > 1) { + if (exponent > 1) { let base:Money = this; for(let i = 1; i < exponent; i++) { base = base.multiply(this); From a0253c8e73aafb8a62425f86dd28ceea5b72ef69 Mon Sep 17 00:00:00 2001 From: Evert Pot Date: Sat, 1 Aug 2020 16:57:55 -0400 Subject: [PATCH 3/4] Fast version --- src/money.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/money.ts b/src/money.ts index a4cbc1a..c22ce11 100644 --- a/src/money.ts +++ b/src/money.ts @@ -115,19 +115,23 @@ export class Money { * * pow currently only supports whole numbers. */ - pow(exponent: number): Money { + pow(exponent: number | bigint): Money { - if (!Number.isInteger(exponent)) { + if (typeof exponent === 'number' && !Number.isInteger(exponent)) { throw new Error('You can currently only use pow() with whole numbers'); } if (exponent > 1) { - let base:Money = this; - for(let i = 1; i < exponent; i++) { - base = base.multiply(this); - } - return base; + const resultBig = this.value ** BigInt(exponent); + return Money.fromSource( + divide(resultBig, PRECISION_M ** (BigInt(exponent)-1n), this.round), + this.currency, + this.round + ); } else { + // This handles the 0, 1 and negative exponent cases. + // This uses an iterative approach and is therefore not going to super + // fast. let base:Money = this; for(let i = 1; i > exponent; i--) { base = base.divide(this); From fb9649a7dae0811d0fba0343dfc80825cc7b0b2c Mon Sep 17 00:00:00 2001 From: Evert Pot Date: Sat, 1 Aug 2020 17:00:27 -0400 Subject: [PATCH 4/4] Update docs --- CHANGELOG.md | 6 ++++++ readme.md | 3 +++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a644503..80fa6ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ Changelog ========= +1.2.0 (2020-08-01) +------------------ + +* Added `pow()` operation. + + 1.1.1 (2020-02-02) ------------------ diff --git a/readme.md b/readme.md index b78e0c2..1439d7c 100644 --- a/readme.md +++ b/readme.md @@ -118,6 +118,9 @@ const result = new Money(10).divide(3); // Multiplication const result = new Money('2000').multiply('1.25'); + +// Powers +const result = new Money(2).pow(8); ``` ### Comparing objects