gentooboontoo / js-quantities

JavaScript library for quantity calculation and unit conversion
http://gentooboontoo.github.io/js-quantities/
MIT License
396 stars 102 forks source link

Display in baseScalar units without changing to SI units #23

Open bombledmonk opened 9 years ago

bombledmonk commented 9 years ago

This may be easy, but I haven't quite teased out if this is possible yet.

Goal: I have data that comes in various magnitudes and I would like to normalize the the string output to the baseScalar while retuning the baseScalar's original label with the appropriate prefix change. The units are not known ahead of time so a simple someqty.to() seems to be out.

Example : input = [1 mW, 1 W, 433 mW, 8 W] desired output = [0.001 W, 1 W, 0.433 W, 8 W]

someqty.toBase() offers the baseScalar number, but it changes the units to SI representation. This works well for seconds and meters, but the representation of 100mW ends up being 0.1 kg*m2/s3.

One can just call someqty.baseScalar for the value, but how does one get the baseScalar's unit without transforming the label into something that is purely si units?

Am I think about this wrong? Is there a decent method converting the base scalar with only a simple prefix change on the output.

gentooboontoo commented 9 years ago

It is not currently possible. I think implementing a method like toPrefix could fill the gap.

For instance, someqty.toPrefix('c') would return converted quantity using centi as prefix. When calling toPrefix without parameter, it would convert to the same units without prefix (for instance, Qty('30 mW').toPrefix(); // 0.03 W).

librilex commented 7 years ago

I tried to write it myself and it seems to work okay. Right now, there is no check implemented if the quantity is unit-less or not. Also, the prefix must come first in the numerator of the unit. But I think this is the only way prefixes are used, right? To use the method toPrefix(prefix):

Qty('10 kW').toPrefix() // outputs quantity with '10000 W'
Qty('10 kW').toPrefix('M') // outputs quantity with '0.01 MW'

I have used three external functions as I needed them for my version of toEng() as well.

Here is my 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;
}

// ... //

assign(Qty.prototype, {
// ... //
  toPrefix: function(prefix) {
      return convert_prefix(this,prefix);
  },
// ... //
}