diff --git a/History.md b/History.md index 70b7328..4922f06 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,9 @@ +1.7.3 / 2018-12-15 +------------------ + +* Fix some inconsistent resulting units when multiplying or dividing +quantities (#94) + 1.7.2 / 2018-03-31 ------------------ diff --git a/README.md b/README.md index 9517b8d..7c070e1 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ and within browsers. ### Browser -Download [latest release v1.7.2](https://raw.github.com/gentooboontoo/js-quantities/v1.7.2/build/quantities.js) +Download [latest release v1.7.3](https://raw.github.com/gentooboontoo/js-quantities/v1.7.3/build/quantities.js) or install it with Bower: bower install js-quantities diff --git a/RELEASE b/RELEASE index f8a696c..661e7ae 100644 --- a/RELEASE +++ b/RELEASE @@ -1 +1 @@ -1.7.2 +1.7.3 diff --git a/bower.json b/bower.json index 93404db..2639cf3 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "js-quantities", - "version": "1.7.2", + "version": "1.7.3", "description": "JavaScript library for quantity calculation and unit conversion", "main": "./build/quantities.js", "keywords": [ diff --git a/build/quantities.esm.js b/build/quantities.esm.js index 19f2ca3..02ab438 100644 --- a/build/quantities.esm.js +++ b/build/quantities.esm.js @@ -1484,9 +1484,9 @@ assign(Qty.prototype, { if (op1.isCompatible(op2) && op1.signature !== 400) { op2 = op2.to(op1); } - var numden = cleanTerms(op1.numerator.concat(op2.numerator), op1.denominator.concat(op2.denominator)); + var numdenscale = cleanTerms(op1.numerator, op1.denominator, op2.numerator, op2.denominator); - return Qty({"scalar": mulSafe(op1.scalar, op2.scalar), "numerator": numden[0], "denominator": numden[1]}); + return Qty({"scalar": mulSafe(op1.scalar, op2.scalar, numdenscale[2]), "numerator": numdenscale[0], "denominator": numdenscale[1]}); }, div: function(other) { @@ -1520,9 +1520,9 @@ assign(Qty.prototype, { if (op1.isCompatible(op2) && op1.signature !== 400) { op2 = op2.to(op1); } - var numden = cleanTerms(op1.numerator.concat(op2.denominator), op1.denominator.concat(op2.numerator)); + var numdenscale = cleanTerms(op1.numerator, op1.denominator, op2.denominator, op2.numerator); - return Qty({"scalar": op1.scalar / op2.scalar, "numerator": numden[0], "denominator": numden[1]}); + return Qty({"scalar": mulSafe(op1.scalar, numdenscale[2]) / op2.scalar, "numerator": numdenscale[0], "denominator": numdenscale[1]}); }, // Returns a Qty that is the inverse of this Qty, @@ -1537,55 +1537,55 @@ assign(Qty.prototype, { } }); -function cleanTerms(num, den) { - num = num.filter(function(val) { +function cleanTerms(num1, den1, num2, den2) { + function notUnity(val) { return val !== UNITY; - }); - den = den.filter(function(val) { - return val !== UNITY; - }); + } + + num1 = num1.filter(notUnity); + num2 = num2.filter(notUnity); + den1 = den1.filter(notUnity); + den2 = den2.filter(notUnity); var combined = {}; - var k; - for (var i = 0; i < num.length; i++) { - if (PREFIX_VALUES[num[i]]) { - k = [num[i], num[i + 1]]; - i++; - } - else { - k = num[i]; - } - if (k && k !== UNITY) { - if (combined[k]) { - combined[k][0]++; + function combineTerms(terms, direction) { + var k; + var prefix; + var prefixValue; + for (var i = 0; i < terms.length; i++) { + if (PREFIX_VALUES[terms[i]]) { + k = terms[i + 1]; + prefix = terms[i]; + prefixValue = PREFIX_VALUES[prefix]; + i++; } else { - combined[k] = [1, k]; - } - } - } - - for (var j = 0; j < den.length; j++) { - if (PREFIX_VALUES[den[j]]) { - k = [den[j], den[j + 1]]; - j++; - } - else { - k = den[j]; - } - if (k && k !== UNITY) { - if (combined[k]) { - combined[k][0]--; + k = terms[i]; + prefix = null; + prefixValue = 1; } - else { - combined[k] = [-1, k]; + if (k && k !== UNITY) { + if (combined[k]) { + combined[k][0] += direction; + var combinedPrefixValue = combined[k][2] ? PREFIX_VALUES[combined[k][2]] : 1; + combined[k][direction === 1 ? 3 : 4] *= divSafe(prefixValue, combinedPrefixValue); + } + else { + combined[k] = [direction, k, prefix, 1, 1]; + } } } } - num = []; - den = []; + combineTerms(num1, 1); + combineTerms(den1, -1); + combineTerms(num2, 1); + combineTerms(den2, -1); + + var num = []; + var den = []; + var scale = 1; for (var prop in combined) { if (combined.hasOwnProperty(prop)) { @@ -1593,14 +1593,15 @@ function cleanTerms(num, den) { var n; if (item[0] > 0) { for (n = 0; n < item[0]; n++) { - num.push(item[1]); + num.push(item[2] === null ? item[1] : [item[2], item[1]]); } } else if (item[0] < 0) { for (n = 0; n < -item[0]; n++) { - den.push(item[1]); + den.push(item[2] === null ? item[1] : [item[2], item[1]]); } } + scale *= divSafe(item[3], item[4]); } } @@ -1619,7 +1620,7 @@ function cleanTerms(num, den) { return a.concat(b); }, []); - return [num, den]; + return [num, den, scale]; } assign(Qty.prototype, { @@ -1990,6 +1991,6 @@ function simplify (units) { }); } -Qty.version = "1.7.2"; +Qty.version = "1.7.3"; export default Qty; diff --git a/build/quantities.js b/build/quantities.js index 0ba470a..c180cf0 100644 --- a/build/quantities.js +++ b/build/quantities.js @@ -1490,9 +1490,9 @@ SOFTWARE. if (op1.isCompatible(op2) && op1.signature !== 400) { op2 = op2.to(op1); } - var numden = cleanTerms(op1.numerator.concat(op2.numerator), op1.denominator.concat(op2.denominator)); + var numdenscale = cleanTerms(op1.numerator, op1.denominator, op2.numerator, op2.denominator); - return Qty({"scalar": mulSafe(op1.scalar, op2.scalar), "numerator": numden[0], "denominator": numden[1]}); + return Qty({"scalar": mulSafe(op1.scalar, op2.scalar, numdenscale[2]), "numerator": numdenscale[0], "denominator": numdenscale[1]}); }, div: function(other) { @@ -1526,9 +1526,9 @@ SOFTWARE. if (op1.isCompatible(op2) && op1.signature !== 400) { op2 = op2.to(op1); } - var numden = cleanTerms(op1.numerator.concat(op2.denominator), op1.denominator.concat(op2.numerator)); + var numdenscale = cleanTerms(op1.numerator, op1.denominator, op2.denominator, op2.numerator); - return Qty({"scalar": op1.scalar / op2.scalar, "numerator": numden[0], "denominator": numden[1]}); + return Qty({"scalar": mulSafe(op1.scalar, numdenscale[2]) / op2.scalar, "numerator": numdenscale[0], "denominator": numdenscale[1]}); }, // Returns a Qty that is the inverse of this Qty, @@ -1543,55 +1543,55 @@ SOFTWARE. } }); - function cleanTerms(num, den) { - num = num.filter(function(val) { + function cleanTerms(num1, den1, num2, den2) { + function notUnity(val) { return val !== UNITY; - }); - den = den.filter(function(val) { - return val !== UNITY; - }); + } + + num1 = num1.filter(notUnity); + num2 = num2.filter(notUnity); + den1 = den1.filter(notUnity); + den2 = den2.filter(notUnity); var combined = {}; - var k; - for (var i = 0; i < num.length; i++) { - if (PREFIX_VALUES[num[i]]) { - k = [num[i], num[i + 1]]; - i++; - } - else { - k = num[i]; - } - if (k && k !== UNITY) { - if (combined[k]) { - combined[k][0]++; + function combineTerms(terms, direction) { + var k; + var prefix; + var prefixValue; + for (var i = 0; i < terms.length; i++) { + if (PREFIX_VALUES[terms[i]]) { + k = terms[i + 1]; + prefix = terms[i]; + prefixValue = PREFIX_VALUES[prefix]; + i++; } else { - combined[k] = [1, k]; - } - } - } - - for (var j = 0; j < den.length; j++) { - if (PREFIX_VALUES[den[j]]) { - k = [den[j], den[j + 1]]; - j++; - } - else { - k = den[j]; - } - if (k && k !== UNITY) { - if (combined[k]) { - combined[k][0]--; + k = terms[i]; + prefix = null; + prefixValue = 1; } - else { - combined[k] = [-1, k]; + if (k && k !== UNITY) { + if (combined[k]) { + combined[k][0] += direction; + var combinedPrefixValue = combined[k][2] ? PREFIX_VALUES[combined[k][2]] : 1; + combined[k][direction === 1 ? 3 : 4] *= divSafe(prefixValue, combinedPrefixValue); + } + else { + combined[k] = [direction, k, prefix, 1, 1]; + } } } } - num = []; - den = []; + combineTerms(num1, 1); + combineTerms(den1, -1); + combineTerms(num2, 1); + combineTerms(den2, -1); + + var num = []; + var den = []; + var scale = 1; for (var prop in combined) { if (combined.hasOwnProperty(prop)) { @@ -1599,14 +1599,15 @@ SOFTWARE. var n; if (item[0] > 0) { for (n = 0; n < item[0]; n++) { - num.push(item[1]); + num.push(item[2] === null ? item[1] : [item[2], item[1]]); } } else if (item[0] < 0) { for (n = 0; n < -item[0]; n++) { - den.push(item[1]); + den.push(item[2] === null ? item[1] : [item[2], item[1]]); } } + scale *= divSafe(item[3], item[4]); } } @@ -1625,7 +1626,7 @@ SOFTWARE. return a.concat(b); }, []); - return [num, den]; + return [num, den, scale]; } assign(Qty.prototype, { @@ -1996,7 +1997,7 @@ SOFTWARE. }); } - Qty.version = "1.7.2"; + Qty.version = "1.7.3"; return Qty; diff --git a/package.json b/package.json index f071ece..b336358 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "main": "./build/quantities.js", "readmeFilename": "README.md", "description": "JavaScript library for quantity calculation and unit conversion", - "version": "1.7.2", + "version": "1.7.3", "homepage": "http://gentooboontoo.github.io/js-quantities/", "repository": { "type": "git", diff --git a/src/quantities.js b/src/quantities.js index 39954f4..6d52c50 100644 --- a/src/quantities.js +++ b/src/quantities.js @@ -6,6 +6,6 @@ import "./quantities/predicates.js"; import "./quantities/conversion.js"; import "./quantities/format.js"; -Qty.version = "1.7.2"; +Qty.version = "1.7.3"; export default Qty;