Closed ericman314 closed 1 year ago
Just for my understanding a few questions:
si
. Now, when I create a unit, is it only defined in the si
system? Is the unit gone when I switch to a different system such as auto
?mi / hr
is not simplified to mph
without defining mph
as a new quantity (formerly we called this "base unit", right?). Do we have to define new quantities for every unit in order to have simplfication working? When does simplification take place and when not?It sounds to me lie we have to create createUnit
to do the smart stuff, and offer a simple interface to generate the actual definitions object behind the scenes. If I'm not mistaken, the old createUnit
in mathjs was layered: it allowed entering an advanced definition of a new unit, but also allows simple input, more user friendly input which is internally transformed into the correct definition.
math.create
is used however, the custom units are gone. BuiltIns.js
:unit: meter, second, ohm, gram, etc. prefix: u, m, k, M, G, etc. base quantity (formerly base unit): The independent quantities, such as LENGTH, TIME, MASS, CURRENT, etc. quantity: The derived quantities: VELOCITY, MOMENTUM, VOLTAGE, ACCELERATION, etc. system: For each system like si, us, cgs, this matches each quantity or base quantity with a preferred unit.
For clarity during this discussion, I'll refer to a complete value like 34 m / s
as a Unit (bold, capitalized). I haven't found a better name yet to differentiate units from Units.
Here is the algorithm behind simplify()
:
30000 kg / m s^2
auto
, then examine the individual units and choose the system that is most represented. In this case, kg
and m
are found in the si system, and s
is found in both the si
and us
systems, so si
is chosen. In the event of a tie, si
is favored.30000 kg / m s^2
matches quantity PRESSURE
which has the definition MASS LENGTH^-1 TIME^-2
.si
system lists Pa
as the preferred unit of PRESSURE
.simplifyThreshold
symbols less than the unsimplified), accept the simplification, otherwise reject it. 30 kPa
.Why is
mi / hr
not simplified tomph
This is because the us
system does not list a preferred unit for VELOCITY
, so the Unit is just built using the us
units for LENGTH and TIME, which gives ft / s
. (But ft / s
is rejected since it is not fewer symbols than mi / hr
.)
In order to make mi / hr
simplify to mph
, the mph
unit must be listed as the preferred VELOCITY
unit in the us
system. This is done by including a unitSystems: { us: { VELOCITY: 'mph' } }
in the config options, or, as this issue proposes, including system: 'us'
in the unit definition for mph
itself.
The old
createUnit
in mathjs was layered: it allowed entering an advanced definition of a new unit, but also allows simple input, more user friendly input which is internally transformed into the correct definition.
That's correct. We made it possible to define a unit by supplying a Unit string, or additional options. This is still the case; see the examples here.
What will change:
Nothing will change for the math.js user. For the UnitMath user, it adds a shortcut which automatically adds the new custom units to the correct system. For math.js's interface with UnitMath, we will just need to add either system: 'auto'
or system: config.unitSystem
to each unit definition.
Thanks for yoru clear explanation Eric, I understand it now. I was missing the part of quantity not being base quantity. I understand now that this is essential to define if you want to be able to simplify to a created unit (like mph
). It makes sense, this way you will only simplify to meaningful quantities instead of random (shorter) quantities.
I think your proposed solution makes sense: automatically creating quanties when adding a new unit if it doesn't match an existing quantity. And of course allowing the user to optionally define a quantity if he wants.
I've updated the UnitMath README. I renamed the system
option to autoAddToSystem
to avoid confusion with other similarly named symbols. I haven't started the implementation yet, but if you would, kindly review the README above (search for addToUnitSystem) and see if that API makes sense to you.
The docs are very clear, and the new name autoAddToSystem
is much more self-explanatory :+1: . Makes sense to me.
Closing this, as I think a lot of the discussion is out-of-date. v1.0.0 completely changes how base units and systems are defined, and should resolve a lot of these issues. Custom units won't automatically be added to systems, but adding them manually will be super, super easy.
A few tests in math.js are still failing; these are related to creating custom units, and expecting those units to be used when simplifying expressions (they are not currently). In UnitMath, a unit has to be part of a system in order for it to appear in a simplified expression. When the chosen unit system is
auto
,N m
becomesJ
, andft lbf
becomesBTU
.Say we do
createUnit(mph, 1 mi/hr)
in math.js. Currently,mi / hr
does not simplify tomph
as we would expect. To fix this, we need to assignmph
as theVELOCITY
unit of theus
system. This is possible if you include additional options toUnitMath
:But math.js doesn't have access to the logic used to match quantities or systems, so it wouldn't be able to produce the
unitSystems
object above. Things get even more complicated if a new quantity is introduced. I imagine that many users of UnitMath (including math.js) will not want to be encumbered by the verbose definitions required to make custom units members of a unit system:We could, however, create a flag that would cause the
unitSystems
andquantities
objects to be created automatically. That way, if we then docreateUnit(mph, 1 mi/hr)
followed by5 mi / hr
, we should get5 mph
. But5 km / hr
will still give5 km/hr
since it's a different unit system.So in math.js, we would merely add the
system: 'auto'
to each custom unit.@harrysarson, @josdejong, any thoughts?
P.S. How it might work:
Just before the units are finished being created in
UnitStore.js
, we look at each unit and if it has thesystem
key, we match its value to existing quantities. If an existing quantity matches, we use that, and if there is not a match, we add an additional quantity (snap_QUANT
or something). Then, ifsystem
is an existing system we use that, and if it is'auto'
then we matchvalue
to a unit system (si
in this case due to them
). Then we add the additional entries toquantities
andunitSystems
. Sincesystem
is part of the unit definition, the user can retrieve the current definitions usingunit.definitions()
, recovering the original options passed.