From 6fa589057e4756ae3c76f7dfbf2295d535e1b1c1 Mon Sep 17 00:00:00 2001 From: Michael Greminger Date: Tue, 13 Jun 2023 03:39:44 -0500 Subject: [PATCH] Big Number Format Fixes (#2956) * test: format bignumber to engineering bug Add tests for correctly handling starting with more then 3 sig figs and targeting 1 or 2 sig figs * lint: * lint: reduce number literal sig figs * fix: engineering notation for bignumber input Corrects handling of cases where the input has 3 or more sig figs and the output is set to 1 or 2 sig figs. * test: add negative format bignumber precision test * fix: use BigNumber for all branches in toEngineering Also, remove string type option from JSDoc for toEngineering since string does support the required interface for the function (the .e property, .mul member function, and the .constructor property would not be correct after this change) * fix: precision 0 for fixed notation and bignumber This fix differentiates precision === 0 and precision === undefined to. After fix, format bignumber for precision 0 matches format number for precision 0. Tests added as well --------- Co-authored-by: Jos de Jong --- src/utils/bignumber/formatter.js | 7 +++--- .../unit-tests/function/string/format.test.js | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/utils/bignumber/formatter.js b/src/utils/bignumber/formatter.js index 6893e66c86..4730761930 100644 --- a/src/utils/bignumber/formatter.js +++ b/src/utils/bignumber/formatter.js @@ -143,7 +143,7 @@ export function format (value, options) { // determine precision from options if (typeof options === 'number') { precision = options - } else if (options.precision) { + } else if (options.precision !== undefined) { precision = options.precision } @@ -212,7 +212,7 @@ export function format (value, options) { /** * Format a BigNumber in engineering notation. Like '1.23e+6', '2.3e+0', '3.500e-3' - * @param {BigNumber | string} value + * @param {BigNumber} value * @param {number} [precision] Optional number of significant figures to return. */ export function toEngineering (value, precision) { @@ -225,7 +225,8 @@ export function toEngineering (value, precision) { let valueStr = valueWithoutExp.toPrecision(precision) if (valueStr.indexOf('e') !== -1) { - valueStr = valueWithoutExp.toString() + const BigNumber = value.constructor + valueStr = new BigNumber(valueStr).toFixed() } return valueStr + 'e' + (e >= 0 ? '+' : '') + newExp.toString() diff --git a/test/unit-tests/function/string/format.test.js b/test/unit-tests/function/string/format.test.js index d6c8773b94..a271dc581e 100644 --- a/test/unit-tests/function/string/format.test.js +++ b/test/unit-tests/function/string/format.test.js @@ -217,6 +217,19 @@ describe('format', function () { assert.strictEqual(bigmath.format(oneThird, 18), '0.333333333333333333') }) + it('should format big numbers with fixed precision', function () { + const oneThird = math.bignumber(1).div(3) + const twoThirds = math.bignumber(2).div(3) + assert.strictEqual(math.format(oneThird, { notation: 'fixed', precision: 10 }), '0.3333333333') + assert.strictEqual(math.format(oneThird.mul(-1), { notation: 'fixed', precision: 10 }), '-0.3333333333') + assert.strictEqual(math.format(twoThirds, { notation: 'fixed', precision: 10 }), '0.6666666667') + assert.strictEqual(math.format(twoThirds, { notation: 'fixed', precision: 20 }), '0.66666666666666666667') + assert.strictEqual(math.format(oneThird, { notation: 'fixed', precision: 20 }), '0.33333333333333333333') + assert.strictEqual(math.format(oneThird, { notation: 'fixed', precision: 0 }), '0') + assert.strictEqual(math.format(twoThirds, { notation: 'fixed', precision: 0 }), '1') + assert.strictEqual(math.format(math.bignumber('123456789.123456789'), { notation: 'fixed', precision: 5 }), '123456789.12346') + }) + describe('engineering notation', function () { const bignumber = math.bignumber @@ -335,6 +348,16 @@ describe('format', function () { assert.strictEqual(math.format(bignumber('0.0000000000001234567890123456789'), { notation: 'engineering', precision: 3 }), '123e-15') assert.strictEqual(math.format(bignumber('0.0000000000001234567890123456789'), { notation: 'engineering', precision: 16 }), '123.4567890123457e-15') }) + it('should format numbers starting with more than 3 sig figs that target 1 or 2 sig figs', function () { + assert.strictEqual(math.format(bignumber(0.333333333333333), { notation: 'engineering', precision: 1 }), '300e-3') + assert.strictEqual(math.format(bignumber(0.333333333333333), { notation: 'engineering', precision: 2 }), '330e-3') + assert.strictEqual(math.format(bignumber(33.33333333333), { notation: 'engineering', precision: 1 }), '30e+0') + assert.strictEqual(math.format(bignumber(333.33333333333), { notation: 'engineering', precision: 2 }), '330e+0') + assert.strictEqual(math.format(bignumber(333333.333333333), { notation: 'engineering', precision: 1 }), '300e+3') + assert.strictEqual(math.format(bignumber(777777.77777777), { notation: 'engineering', precision: 1 }), '800e+3') + assert.strictEqual(math.format(bignumber(777777.77777777), { notation: 'engineering', precision: 2 }), '780e+3') + assert.strictEqual(math.format(bignumber(-0.000000000777777), { notation: 'engineering', precision: 2 }), '-780e-12') + }) }) describe('non decimal base formatting', function () {