diff --git a/src/function/statistics/variance.js b/src/function/statistics/variance.js index 814a17442..13720f293 100644 --- a/src/function/statistics/variance.js +++ b/src/function/statistics/variance.js @@ -97,7 +97,7 @@ export const createVariance = /* #__PURE__ */ factory(name, dependencies, ({ typ * @private */ function _var (array, normalization) { - let sum = 0 + let sum let num = 0 if (array.length === 0) { @@ -107,7 +107,7 @@ export const createVariance = /* #__PURE__ */ factory(name, dependencies, ({ typ // calculate the mean and number of elements deepForEach(array, function (value) { try { - sum = add(sum, value) + sum = sum === undefined ? value : add(sum, value) num++ } catch (err) { throw improveErrorMessage(err, 'variance', value) @@ -118,10 +118,10 @@ export const createVariance = /* #__PURE__ */ factory(name, dependencies, ({ typ const mean = divide(sum, num) // calculate the variance - sum = 0 + sum = undefined deepForEach(array, function (value) { const diff = subtract(value, mean) - sum = add(sum, multiply(diff, diff)) + sum = sum === undefined ? multiply(diff, diff) : add(sum, multiply(diff, diff)) }) if (isNaN(sum)) { diff --git a/test/unit-tests/expression/transform/std.transform.test.js b/test/unit-tests/expression/transform/std.transform.test.js index d2e905fc8..656e6474d 100644 --- a/test/unit-tests/expression/transform/std.transform.test.js +++ b/test/unit-tests/expression/transform/std.transform.test.js @@ -1,4 +1,5 @@ import assert from 'assert' +import approx from '../../../../tools/approx' import math from '../../../../src/bundleAny' const Unit = math.Unit @@ -34,7 +35,6 @@ describe('std', function () { it('should throw an error if called with invalid type of arguments', function () { assert.throws(function () { std(new Date(), 2) }, /Cannot calculate std, unexpected type of argument/) - assert.throws(function () { std(new Unit(5, 'cm'), new Unit(10, 'cm')) }, /Cannot calculate std, unexpected type of argument/) assert.throws(function () { std(2, 3, null) }, /Cannot calculate std, unexpected type of argument/) assert.throws(function () { std([2, 3, null]) }, /Cannot calculate std, unexpected type of argument/) assert.throws(function () { std([[2, 4, 6], [1, 3, 5]], 'biased', 0) }, /Cannot convert "biased" to a number/) @@ -49,4 +49,25 @@ describe('std', function () { const expression = math.parse('std(1,2,3)') assert.strictEqual(expression.toTex(), '\\mathrm{std}\\left(1,2,3\\right)') }) + + it('should compute the standard deviation value of quantities with units', function () { + const a = new Unit(2, 'cm') + const b = new Unit(5, 'cm') + const c = new Unit(8, 'cm') + const res = math.unit(3, 'cm') + approx.equal(std([a, b, c]).toNumber('cm'), res.toNumber('cm')) + }) + + it('should compute the standard deviation value of quantities with compatible units', function () { + const a = math.unit(1, 'm') + const b = math.unit(50, 'cm') + const c = math.unit(math.sqrt(1250), 'cm') + approx.equal(std([a, b]).toNumber('cm'), c.toNumber('cm')) + }) + + it('should not compute the standard deviation value of quantities with incompatible units', function () { + const a = math.unit(1, 'm') + const b = math.unit(50, 'kg') + assert.throws(function () { std([a, b]) }, /Units do not match/) + }) }) diff --git a/test/unit-tests/expression/transform/variance.transform.test.js b/test/unit-tests/expression/transform/variance.transform.test.js index 73d41ee62..8a99c2b34 100644 --- a/test/unit-tests/expression/transform/variance.transform.test.js +++ b/test/unit-tests/expression/transform/variance.transform.test.js @@ -1,7 +1,7 @@ import assert from 'assert' +import approx from '../../../../tools/approx' import math from '../../../../src/bundleAny' -const Unit = math.Unit const variance = math.expression.transform.variance describe('variance', function () { @@ -34,7 +34,6 @@ describe('variance', function () { it('should throw an error if called with invalid type of arguments', function () { assert.throws(function () { variance(new Date(), 2) }, /Cannot calculate variance, unexpected type of argument/) - assert.throws(function () { variance(new Unit(5, 'cm'), new Unit(10, 'cm')) }, /Cannot calculate variance, unexpected type of argument/) assert.throws(function () { variance(2, 3, null) }, /Cannot calculate variance, unexpected type of argument/) assert.throws(function () { variance([2, 3, null]) }, /Cannot calculate variance, unexpected type of argument/) assert.throws(function () { variance([[2, 4, 6], [1, 3, 5]], 'biased', 0) }, /Cannot convert "biased" to a number/) @@ -49,4 +48,24 @@ describe('variance', function () { const expression = math.parse('variance(1,2,3)') assert.strictEqual(expression.toTex(), '\\mathrm{Var}\\left(1,2,3\\right)') }) + + it('should compute the variance of quantities with units', function () { + const a = math.unit(10, 'cm') + const b = math.unit(20, 'cm') + const c = math.unit(50, 'cm^2') + approx.equal(variance([a, b]).toNumber('cm^2'), c.toNumber('cm^2')) + }) + + it('should compute the variance of quantities with compatible units', function () { + const a = math.unit(1, 'm') + const b = math.unit(50, 'cm') + const c = math.unit(1250, 'cm^2') + approx.equal(variance([a, b]).toNumber('cm^2'), c.toNumber('cm^2')) + }) + + it('should not compute the variance of quantities with incompatible units', function () { + const a = math.unit(1, 'm') + const b = math.unit(50, 'kg') + assert.throws(function () { variance([a, b]) }, /Units do not match/) + }) }) diff --git a/test/unit-tests/function/statistics/std.test.js b/test/unit-tests/function/statistics/std.test.js index 06d75e33b..2ab8ba085 100644 --- a/test/unit-tests/function/statistics/std.test.js +++ b/test/unit-tests/function/statistics/std.test.js @@ -106,7 +106,6 @@ describe('std', function () { it('should throw an error if called with invalid type of arguments', function () { assert.throws(function () { std(new Date(), 2) }, /Cannot calculate std, unexpected type of argument/) - assert.throws(function () { std(new Unit(5, 'cm'), new Unit(10, 'cm')) }, /Cannot calculate std, unexpected type of argument/) assert.throws(function () { std(2, 3, null) }, /Cannot calculate std, unexpected type of argument/) assert.throws(function () { std([2, 3, null]) }, /Cannot calculate std, unexpected type of argument/) assert.throws(function () { std([[2, 4, 6], [1, 3, 5]], 'biased', 0) }, /Cannot convert "biased" to a number/) @@ -121,4 +120,25 @@ describe('std', function () { const expression = math.parse('std(1,2,3)') assert.strictEqual(expression.toTex(), '\\mathrm{std}\\left(1,2,3\\right)') }) + + it('should compute the standard deviation value of quantities with units', function () { + const a = new Unit(2, 'cm') + const b = new Unit(5, 'cm') + const c = new Unit(8, 'cm') + const res = math.unit(3, 'cm') + approx.equal(std([a, b, c]).toNumber('cm'), res.toNumber('cm')) + }) + + it('should compute the standard deviation value of quantities with compatible units', function () { + const a = math.unit(1, 'm') + const b = math.unit(50, 'cm') + const c = math.unit(math.sqrt(1250), 'cm') + approx.equal(std([a, b]).toNumber('cm'), c.toNumber('cm')) + }) + + it('should not compute the standard deviation value of quantities with incompatible units', function () { + const a = math.unit(1, 'm') + const b = math.unit(50, 'kg') + assert.throws(function () { std([a, b]) }, /Units do not match/) + }) }) diff --git a/test/unit-tests/function/statistics/variance.test.js b/test/unit-tests/function/statistics/variance.test.js index 166304d4d..d5d8be319 100644 --- a/test/unit-tests/function/statistics/variance.test.js +++ b/test/unit-tests/function/statistics/variance.test.js @@ -1,9 +1,9 @@ import assert from 'assert' +import approx from '../../../../tools/approx' import math from '../../../../src/bundleAny' const BigNumber = math.BigNumber const Complex = math.Complex const DenseMatrix = math.DenseMatrix -const Unit = math.Unit const variance = math.variance describe('variance', function () { @@ -109,7 +109,6 @@ describe('variance', function () { it('should throw an error if called with invalid type of arguments', function () { assert.throws(function () { variance(new Date(), 2) }, /Cannot calculate variance, unexpected type of argument/) - assert.throws(function () { variance(new Unit(5, 'cm'), new Unit(10, 'cm')) }, /Cannot calculate variance, unexpected type of argument/) assert.throws(function () { variance(2, 3, null) }, /Cannot calculate variance, unexpected type of argument/) assert.throws(function () { variance([2, 3, null]) }, /Cannot calculate variance, unexpected type of argument/) assert.throws(function () { variance([[2, 4, 6], [1, 3, 5]], 'biased', 0) }, /Cannot convert "biased" to a number/) @@ -128,4 +127,24 @@ describe('variance', function () { const expression = math.parse('variance(1,2,3)') assert.strictEqual(expression.toTex(), '\\mathrm{Var}\\left(1,2,3\\right)') }) + + it('should compute the variance of quantities with units', function () { + const a = math.unit(10, 'cm') + const b = math.unit(20, 'cm') + const c = math.unit(50, 'cm^2') + approx.equal(variance([a, b]).toNumber('cm^2'), c.toNumber('cm^2')) + }) + + it('should compute the variance of quantities with compatible units', function () { + const a = math.unit(1, 'm') + const b = math.unit(50, 'cm') + const c = math.unit(1250, 'cm^2') + approx.equal(variance([a, b]).toNumber('cm^2'), c.toNumber('cm^2')) + }) + + it('should not compute the variance of quantities with incompatible units', function () { + const a = math.unit(1, 'm') + const b = math.unit(50, 'kg') + assert.throws(function () { variance([a, b]) }, /Units do not match/) + }) })