-
Notifications
You must be signed in to change notification settings - Fork 491
More readable to_compact()
#566
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
It is largely a matter of taste but I find "0.1 millimeter" easier to read than "100 micrometer". It is even more blatant in higher dimensions: 100000 nanometer^2 == 0.1 micrometer^2, pint currently compacts "1e-13 meter" into the former. (The implementation of `to_compact()` enforces a magnitude `> 0`.) With this patch one gets the latter. The tests are updated accordingly.
|
Thanks for the PR. What about |
|
I agree with @hgrecco. Though, what would be really slick (in my opinion) is an optional argument for decimal precision instead of forcing a compact representation on the user. That way, pint could return whatever prefix of a unit is necessary to have For example: |
|
Ok, my thoughts on your comments, where it is shown that @JesterEE's proposition is easy to implement but I lack a good name for it. First of all, I personally prefer 0.123 millimeter to 123 micrometer ;-). So, matter of taste again. In that sense, giving the choice to the user seems to be the way to go. There is a magnitude span of 1000 between two standard metric prefixes. Currently the (FWIW it's also the choice made by Boost Units) This proposed PR gives Other options could be This is all controlled by a single parameter (and its counterpart for negative So do we want that and more importantly what should we call it? I'd really want it, I'm willing to implement it but I have no clue on how to name it. |
|
Let's try to dig at the reasons why someone may prefer one unit over another (it's different for everyone) and how we can express that as simple rule to tell pint how you prefer your number for a given quantity. Hopefully we can find a rule that is consistent across different units ( @JesterEE's suggested The way I would describe how In code, I would express this as defining a lower threshold (default=1) used to determine the largest unit. This is essentially the same as @JesterEE'd The upper threshold is dictated by the minimum of the exponents in the units. For example, meter will have the range I think the reason you prefer If you prefer If a new parameter or context were to be added, it would be mutually exclusive with the existing unit argument of Maybe the maximum unit where the number is greater than 0.001 rule isn't really what we want. Perhaps it would be better to select the unit closest to the base unit: if quantity is less than Maybe a better solution to determine the preferred unit is to write a method that wraps Can you propose a function (that everyone can agree on) that can determine what the preferred units are for a given quantity? I don't think this problem can be reduced down to specifying one or two numbers as an argument to a function. |
|
It's great that other's are taking some active interest in this PR! The more voices, the better chance we have on getting it right! I do agree I'll throw another one in: for our purposes
Let's brainstorm some more! to_compact method argument name suggestions
@emmanelletrong @onealj import pint
u = pint.UnitRegistry()
'{:0.2f}'.format(u('1000 min').to_compact())
>>> 1.00 kilominute
'{:0.2f}'.format(u('1000 min').to('sec').to_compact())
>>> 60.00 kilosecHowever, I would caution automating this too much because in the current state of import pint
u = pint.UnitRegistry()
time = u('6000 sec')
time.compatible_units() # Note some time scaled units (e.g. minute) are not defined here!
>>> frozenset({<Unit('shake')>,
>>> <Unit('sidereal_second')>,
>>> <Unit('second')>,
>>> <Unit('sidereal_minute')>,
>>> <Unit('sidereal_hour')>,
>>> <Unit('sidereal_day')>,
>>> <Unit('week')>,
>>> <Unit('work_month')>,
>>> <Unit('sidereal_month')>,
>>> <Unit('tropical_month')>,
>>> <Unit('synodic_month')>,
>>> <Unit('work_year')>,
>>> <Unit('gregorian_year')>,
>>> <Unit('julian_year')>,
>>> <Unit('sidereal_year')>,
>>> <Unit('leap_year')>,
>>> <Unit('eon')>})
'{:0.2f}.format(time.to_compact()) # Lets assume to_compact arbitrarily tries all the compatible units till it finds a "good" one, though this would be a bad approach
>>> 1.67 sidereal_hour
'{:0.2f}.format(time.to_compact()) # Maybe a different one this time ... let's see
>>> 100.27 sidereal_minute
'{:0.2f}.format(time.to_compact(unit_priority=['second', 'minute', 'hour', 'day', 'week', 'month', 'year'])) # 'If' to_compact would do this ... provide yet another argument
>>> 100 minute
'{:0.2f}.format(time.to_compact((unit_priority=['year', 'month', 'week', 'day', 'hour', 'minute', 'second'])) # A different priority
>>> 1.67 hourAlso, I don't think specifying the desired unit in import pint
u = pint.UnitRegistry()
(1.23e3*u.m).to('km')
>>> 1.23 kilometerI think that I'd rather see an under-engineered solution that doesn't do it all, but is easy to use rather than an over-engineered solution that takes lots of input to get right. But, if you want to implement all that, it may prove to be useful and I will be nothing short of encouraging along the way. Though it's probably way more involved than @emmanelletrong had in mind for this PR. |
|
@JesterEE is completely right when mentions that the purpose of
I do not have yet a strong opinion about the other names. Regarding non-base10 units, I think it should be done based on the active system and we might want to move that discussion to another thread/PR. If we improve As a historical note, when Systems and Groups were implemented I played with the idea of introducing a way to describe "order and preferred units". The idea was that the system (or the group, I was not clear where was best to do it) contains information about which units (among all in available) constitute a useful ladder. So you could ask While the syntax is not important, I think it is useful to show to clarify the idea. I tried different, one was: where the star shows the base unit of system. You could also have something for time I think something like this could be more extendable and robust, useful for |
|
I like the It sounds like the Rather than having an ever growing list of arguments to try to inform Specifying a dialect class that defines a function to convert a quantity into the best human readable format based on rules implemented in that class would mean To me, the name |
|
Just a comment regarding the unit parameter. Its purpose was to help pint regarding conversion between equivalent simple/compound units. So instead of having I think that the unit parameter in |
|
Bu the way, comment in issue #569 about what should be included in 0.9 |
|
While I think this discussion was very useful, I am closing this PR until we can get a good solution. |
It is largely a matter of taste but I find "0.1 millimeter" easier to read than "100 micrometer". It is even more blatant in higher dimensions:
100000 nanometer^2 == 0.1 micrometer^2,
pint currently compacts "1e-13 meter" into the former. (The implementation of
to_compact()enforces a magnitude> 0.) With this patch one gets the latter. The tests are updated accordingly.