diff --git a/pint/quantity.py b/pint/quantity.py index 597355d..0959be4 100644 --- a/pint/quantity.py +++ b/pint/quantity.py @@ -21,7 +21,7 @@ from .errors import (DimensionalityError, OffsetUnitCalculusError, from .definitions import UnitDefinition from .compat import string_types, ndarray, np, _to_magnitude, long_type from .util import (logger, UnitsContainer, SharedRegistryObject, - to_units_container) + to_units_container, infer_base_unit) def _eq(first, second, check_all): @@ -269,14 +269,14 @@ class _Quantity(SharedRegistryObject): return self if unit is None: - q_base = self.to_base_units() - else: - q_base = self.to(unit) + unit = infer_base_unit(self) + + q_base = self.to(unit) magnitude = q_base.magnitude - unit_items = q_base._units.items() - unit_str = unit_items[0][0] - unit_power = unit_items[0][1] + # Only changes the prefix on the first unit in the UnitContainer + unit_str = q_base._units.items()[0][0] + unit_power = q_base._units.items()[0][1] if unit_power > 0: power = math.floor((math.log(magnitude, 1000) / unit_power)) * 3 @@ -290,19 +290,10 @@ class _Quantity(SharedRegistryObject): else: prefix = _base_powers[power] - new_unit = "{prefix}{unit_str}**{unit_power}".format( - prefix=prefix, unit_str=unit_str, unit_power=unit_power) - if len(unit_items) == 1: - return self.to(new_unit) - else: - # If there are more units in the registry, combine them now. - # This unit might not make a lot of sense, - # but it will at least be valid - combined_new_unit = self._REGISTRY(new_unit) - for unit, power in unit_items[1:]: - combined_new_unit *= getattr(self._REGISTRY, unit) ** power + new_unit_str = prefix+unit_str + new_unit_container = q_base._units.rename(unit_str, new_unit_str) - return self.to(combined_new_unit) + return self.to(new_unit_container) # Mathematical operations def __int__(self): diff --git a/pint/util.py b/pint/util.py index 2c59061..647defa 100644 --- a/pint/util.py +++ b/pint/util.py @@ -622,3 +622,43 @@ def to_units_container(unit_like, registry=None): return ParserHelper.from_string(unit_like) elif dict in mro: return UnitsContainer(unit_like) + +_prefixes = {'atto', + 'exa', + 'femto', + 'giga', + 'kilo', + 'mega', + 'micro', + 'milli', + 'nano', + 'peta', + 'pico', + 'tera', + 'yocto', + 'yotta', + 'zepto', + 'zetta', + 'centi', + 'deci', + 'deca', + 'hecto', + 'kibi', + 'mebi', + 'gibi', + 'tebi', + 'pebi', + 'exbi', + 'zebi', + 'yobi'} + +_prefixes_regex = '^('+'|'.join(_prefixes)+')+' +_find_prefixes = re.compile(_prefixes_regex) + + +def infer_base_unit(q): + """Return UnitsContainer of q with all prefixes stripped.""" + return UnitsContainer( + dict((_find_prefixes.sub('', unit), power) for + unit, power in q._units.items()) + )