Frequently asked questions#

Why the name Pint?#

Pint is a unit and sounds like Python in the first syllable. Most important, it is a good unit for beer.

How can I avoid magnitude floating point issues?#

By default, UnitRegistry uses float for magnitudes, which is subject to the usual floating-point rounding behavior:

>>> import pint
>>> ureg = pint.UnitRegistry()
>>> ureg("1 gallon").to("l")
Quantity(3.785411783999999, "liter")

If you need exact arithmetic instead, pass non_int_type when creating the registry:

>>> import decimal
>>> ureg = pint.UnitRegistry(non_int_type=decimal.Decimal)
>>> ureg("1 gallon").to("l")
Quantity(Decimal('3.785411784000000000000000000'), "liter")

or, for exact fractions:

>>> import fractions
>>> ureg = pint.UnitRegistry(non_int_type=fractions.Fraction)

This avoids floating-point noise entirely (no rounding to begin with), at the cost of some performance compared to plain float.

How can I avoid exponent floating point issues?#

Combining quantities raised to fractional powers (e.g. multiplying and dividing several quantities each raised to a different fractional exponent) can leave a tiny floating-point residual on an exponent that should be an exact integer or zero, instead of the number of a whole quantity you might expect, e.g. meter ** 0.9999999999999998 instead of exactly meter ** 1.

Converting the quantity with Quantity.to(), Quantity.to_base_units(), or Quantity.to_reduced_units() recomputes the units against the requested target and resolves this: the result has exactly the units you asked for, with no leftover noise.

Note

Formatters may round the displayed exponent, hiding the issue rather than fixing it: meter ** 0.9999999999999998 still prints as meter ** 1, even though the stored exponent is not exactly 1.

Using Fraction or int avoids this noise. Ten multiplications by meter ** 0.1 don’t quite add up to exactly meter ** 1; ten multiplications by meter ** Fraction(1, 10) do:

>>> u = ureg.Unit("meter") ** 0.1
>>> for _ in range(9):
...     u = u * ureg.Unit("meter") ** 0.1
>>> u == ureg.Unit("meter")
False

>>> import fractions
>>> ureg2 = pint.UnitRegistry(non_int_type=fractions.Fraction)
>>> u3 = ureg2.Unit("meter") ** fractions.Fraction(1, 10)
>>> for _ in range(9):
...     u3 = u3 * ureg2.Unit("meter") ** fractions.Fraction(1, 10)
>>> u3 == ureg2.Unit("meter")
True

This comes at a performance cost (roughly 25% slower than plain float for typical arithmetic), and it only stays exact as long as every exponent is exact: combining an exact Fraction exponent with an ordinary float exponent on the same unit produces a float result, the same noise-prone type this is meant to avoid:

>>> Q_ = ureg2.Quantity
>>> a = Q_(1, ureg2.m ** fractions.Fraction(8, 10))
>>> b = Q_(1, ureg2.m ** 0.5)
>>> c = a * b
>>> c.units._units["meter"]
1.3
>>> type(c.units._units["meter"])
<class 'float'>

You mention other similar Python libraries. Can you point me to those?#

natu

Buckingham

Magnitude

SciMath

Python-quantities

Unum

Units

udunitspy

SymPy

cf units

astropy units

yt

measurement

If you’re aware of another one, please contribute a patch to the docs.