I have this problem I'd like to solve with python pint.
I have then 2 new abstract units "points" and "usd" and reuse the "time" unit "minute".
I can use simple mathematical operations for that :
import pint
units = pint.UnitRegistry()
units.define("usd = [usd]")
units.define("points = [points]")
a = 0.29 * units.points / units.minutes
b = 118 * units.points / (17.35 * units.usd)
Now I was to have 5 minutes to usd but of course I need to to the computation myself, do I multiply or divide by a ? Same for b ? The answer is one of those line:
5 * units.minutes * a * b
5 * units.minutes * a / b
5 * units.minutes / a * b
5 * units.minutes / a / b
Of course, only one of those line gives unit "usd". So I could compute all the possible ones and keep the one where the unit is usd. Turns out it's the second one.
I wish the library would find a path to convert my "5 minutes" using those relations in this context.
I have read about pint contexts but I didn't find any working solution. I was hoping to be able to write something like this:
(5 * units.minutes).to(units.usd, mycontext_with_the_two_equations)
From that conversion table, you need to find "usd per minute" which is a/b
:
a/b = (0.29 * units.points / units.minutes) / (118 * units.points / (17.35 * units.usd))
= (0.29 * (17.35 * units.usd)) / (units.minutes * 118)
= 0.0426*units.usd / units.minutes
Then you can multiply it with 5, here is the full code:
import pint
units = pint.UnitRegistry()
units.define("usd = [usd]")
units.define("points = [points]")
points_per_minute = 0.29 * units.points / units.minute
points_per_usd = 118 * units.points / (17.35 * units.usd)
usd_per_minute = points_per_minute / points_per_usd
value_in_usd = (5 * units.minute) * usd_per_minute
print(f"5 minutes is worth approximately: {value_in_usd:.2f}")
# 5 minutes is worth approximately: 0.21 usd
You create context, register you conversion table to that context. Then you add that context into unit registry and now you can use unit registry like units().to()
import pint
units = pint.UnitRegistry()
units.define("usd = [usd]")
units.define("points = [points]")
context = pint.Context("minute-points-usd")
context.add_transformation("minute", "points", lambda ureg, x: x * 0.29 * ureg.points / ureg.minute)
context.add_transformation("points", "usd", lambda ureg, x: x / (118 * ureg.points / (17.35 * ureg.usd)))
units.add_context(context)
a = units("5 min").to("usd", "minute-points-usd")
print(a)
Same like above example, but this time you enter context using with
statement:
import pint
units = pint.UnitRegistry()
units.define("usd = [usd]")
units.define("points = [points]")
c = pint.Context("minute-points-usd")
c.add_transformation("minute", "points", lambda ureg, x: x * 0.29 * ureg.points / ureg.minute)
c.add_transformation("points", "usd", lambda ureg, x: x / (118 * ureg.points / (17.35 * ureg.usd)))
units.add_context(c)
with units.context("minute-points-usd"):
value_in_usd = (5 * units.minute).to("usd")
#value_in_usd = units("5 min").to("usd")