Open bombledmonk opened 9 years ago
Yep, would be very nice. Currently trying to write this myself, but i'm not very good in JS.
It would be an interesting feature to implement. I would like it leverages extensibility through formatters (https://github.com/gentooboontoo/js-quantities#formatting-quantities).
var engFormatter = function(scalar, units) { /*...*/ };
// ...
qty.format(engFormatter);
// or by setting engineering notation as default formatter
Qty.formatter = engFormatter;
qty.format();
If this formatter is included in the library, a Qty#toEng
helper method could also be added.
I wrote a little code to get this done. It sure isn't pretty, but it gets the deal done. I was not able to create it as a formatter, just as a method. Maybe someone else knows how to do it? This is the way you can use it:
Qty('.0001 mA').toEng() // outputs quantity of '100 nA' (this is correct, 100 µA would be 0.1 mA)
Qty('1200 W').toEng() // outputs quantity of '1.2 MW'
Qty('0.8 W').toEng() // outputs quantity of '800 mW'
As my toPrefix()-method, this function does not work with unit-less quantities. I used external functions as I rely on them with my toPrefix() as well.
Here is the code:
// Get prefix from unit, eg. 'kW' --> 'k'
function get_prefix(qty) {
var prefix;
if (UNITS[qty.numerator[0]][2] == "prefix") {
prefix = UNITS[qty.numerator[0]][0][0];
}
else {
prefix = "";
}
return prefix;
}
// Get unit base, eg. 'kW' --> 'W'
function get_unit_base(qty) {
var unit_base, prefix;
prefix = get_prefix(qty);
if (prefix.length === 1) {
unit_base = qty.units().substr(1);
}
else {
unit_base = qty.units();
}
return unit_base;
}
// Convert unit to defined prefix,
// eg. no prefix: '0.1 kW' --> '100 W' or prefix 'm': '0.35 W' --> '350 mW'
function convert_prefix(qty, prefix) {
var prefix, unit_base, target, qty, q;
if (prefix == undefined || prefix == null || prefix == 1) {
prefix = "";
}
unit_base = get_unit_base(qty);
target = Qty(prefix+unit_base);
q = divSafe(qty.baseScalar, target.baseScalar);
target = Qty({"scalar": q, "numerator": target.numerator, "denominator": target.denominator});
return target;
}
// Format quantity to engineering style (only 10^(3*n) prefixes)
function formatEng(scalar, units) {
var qty, q, subtrhnd, pow_10, unit_base, prefix, target;
var powerPrefix = {
"24" : "<yotta>",
"21" : "<zetta>",
"18" : "<exa>",
"15" : "<peta>",
"12" : "<tera>",
"9" : "<giga>",
"6" : "<mega>",
"3" : "<kilo>",
"-3" : "<milli>",
"-6" : "<micro>",
"-9" : "<nano>",
"-12" : "<pico>",
"-15" : "<femto>",
"-18" : "<atto>",
"-21" : "<zepto>",
"-24" : "<yocto>"};
qty = Qty(scalar,units);
q = divSafe(Math.log(qty.baseScalar), Math.log(1e3));
if (Number.isInteger(q)) {
subtrhnd = 0; // so that for example '3 km' does not get converted to '3000 m'
}
else {
subtrhnd = 1;
}
pow_10 = 3 * Math.ceil(q - subtrhnd);
if (pow_10 === -0 || pow_10 === +0) {
prefix = "";
}
else {
prefix = UNITS[powerPrefix[pow_10]][0][0];
}
unit_base = get_unit_base(qty);
target = Qty(qty.baseScalar * Math.pow(10, -pow_10) + ' ' + prefix + unit_base);
return target;
}
// ... //
assign(Qty.prototype, {
// ... //
toEng: function() {
return formatEng(this.baseScalar,this.units())
},
// ... //
});
This may not be necessary, but it would be nice to have a feature that could normalize labels to powers of 10^(3*n) given the prominence of engineering notation.
Example:
Qty('.0001 mA').toEng() // output = 100 uA