Comments (37)
C) Use only QuantityFormat
implementation(s) to handle compound quantities.
from indriya.
A) Model CompoundQuantity and if required CompoundUnit in a similar way as e.g. JSR 310's TemporalAmount.
from indriya.
B) Model CompoundUnit only to assist QuantityFormat
implementation(s) when dealing with compound quantities like 48°30′00″
or 2.8 feet
.
from indriya.
I created an approach to a CompoundQuantity Please have a look and comment here or VOTE using the GitHub "Like" function.
If there is a benefit in keeping CompoundUnit especially for formatting, the two may co-exist and e.g. a CompoundQuantity
may be created by passing a CompoundUnit
and a collection of numeric values. CompoundQuantity
is backed by a LinkedHashMap
to preserve the order, e.g. 6ft 3in
rather than a mix-up. If CompoundUnit
was able to return its units in a similar way, then the two classes may co-exist in a synergetic way. If we want to extend Quantity
formatting to CompoundQuantity
, it may require an API interface (somewhat similar to TemporalAmount
in the JDK) otherwise it may not be required in the API, that's up for discussion. Since the state and value of a CompoundQuantity
cannot be retrieved without conversion like the to() method (if this should be called differently for a CompoundQuantity
please advise, it was just a first draft) it seems to make no sense to implement or inherit the Quantity
interface IMO.
from indriya.
I can conceive CompoundQuantity
as a generalization of TemporalAmount
, but do we have a use case for it (other than temporal)? Compound quantities like "2 feet and 6 inches" is the same quantity than "2.5 feet". Displaying such value as "2 feet and 6 inches" can be considered as QuantityFormat
work. This is different for TemporalAmount
because of the complication of calendars (leap seconds, etc.). But I'm not aware of any such ambiguities for length measurements for example?
from indriya.
We did have to model container sizes like Container Dimensions I managed to overcome it in 363 by doing something along the lines of Quantities.getQuantity(8, FOOT).add(Quantities.getQuantity(6, INCH)
. It works and if we wanted to improve quantity formatting with certain patterns like ft in
(JSR 310 also does offer all sorts of things, JodaTime even a bit more) we could also do that. We are in a story-defining phase, if you want please create another issue/story for quantity formatting. The question is, if assuing we handle it with formatting only, such formatter could use a CompoundUnit
like FOOT.compound(INCH)
as a formatting hint? Currently this is still a discussion phase. Once the JSR is approved (ballot ends in a week) and the EG hits a critical mass, I would like to do a formal vote on certain things like do we need a CompoundQuantity or do we need a CompoundUnit with simple answers like +1/-1.
from indriya.
I think we can handle that with formatter only. For example when formatting 48.5 as an angle like 48°30′00″, I can use an AngleFormat
class and set its pattern to "DD°MM′SS″" where DD stands for degrees, MM stands for minutes and SS stands for seconds (similar approach than patterns in date format).
Wouldn't it be safer to restrict units to non-compound quantities? Otherwise it would introduce a complexity in calculation or unit conversions which is not necessary if we can address the same needs with formatter.
from indriya.
AngleFormat
(in SIS I assume) could be a good inspiration, CompoundUnit also mentions DD°MM′SS″
as another example for a compound unit. The class that serves as a discussion base (also deprecated it like CompoundUnit
as it may change or even go away later) is not meant to be directly converted or calculated on for that reason. Only results of methods like get()
or to()
.
from indriya.
The following 3 options are up for discussion:
Please vote (if you want also for multiple, please not for all of them if possible;-) using the +"Like"
button here.
from indriya.
Maybe I missed the point (tell me if I have): would the idea of preserving a qty like 6 ft 4 inches
as a compound facilitate better maths? e.g. 6ft 4in
+ 6ft 2in
= 12ft 6in
(or 12.5 ft
)
Since the alternative of 6ft 4in
is 6.3333333333333 ft
starts to feed precision errors when we do maths operations?
from indriya.
Thanks for voting and the input. Those are valid questions and challenges we should answer together. @desruisseaux mentioned that Apache SIS mainly for quantities like Angle
. Therefore in a broader context maybe formatting alone is not enough...?
from indriya.
from indriya.
Martin/Chris,
Thanks for raising those points and discussing possible solutions to issues like the loss of precision. That is very similar to e.g. what JSR 354 and other Monetary libraries face when it comes to monetary amounts. Some frameworks and financial apps therefore store the amounts as the smallest fraction, e.g. 250 cent
for 2€ 50cent
. This could be an approach here, too.
from indriya.
@desruisseaux and @keilw,
Decomposing to the smallest unit is a fine approach if all units are of the same system, but if not we'll still get the same floating point inaccuracies. While this is an edge case, there are a handful of countries that use odd mixes of metric and imperial system where this could pop up.
from indriya.
@ejberry Thanks for the input. Everyone who is contributor or EG member is more than welcome to fork Indriya and propose a PR around this or other challenges. Should get the QuantityFormat into the API soon, then what's already refactored as AbstractQuantityFormat.
from indriya.
To clarify, let's assume the following two cases:
- 6 ft. 4 in. (76 in.)
- 6 ft. 4 ft. (10 ft.)
The first case has two quantities of different units while the second case has two quantities of the same unit, but both can be decomposed.
If I were to attempt to design a solution for formatting compounded quantities, should quantities that share a unit be decomposed?
from indriya.
Thanks for the input. The draft of a CompoundQuantity
does not allow duplication of the same unit. JSR 310 does, although its JavaDoc speaks of unique without duplication, but there in theory the List of TemporalUnit
entries may contain the same unit twice. So far in this case a Set
was used.
At the moment if you add 6 ft
. and 4 ft
. the resulting Quantity
is 10 ft
. And even without a dedicated QuantityFormat
API element existing implementations would properly format that.
However adding 6 ft
. and 76 in
. right now this Quantity will end up as FEET because it was the first element in the operation. Unless you did 6ft.to(INCH)
first, or reversed the addition by adding 6 ft
. to 76 in
. So even without a dedicated CompoundQuantity
(right now there is a decent majority for C) we would have to ensure Quantity
implementations can somehow keep track of all the operations that were applied before getting to a new Quantity
and which one e.g. is the smallest?
from indriya.
I see. Assuming we stick with the current draft of CompoundQuantity
, would it be possible to utilize ComparableQuantity
(or just ComparableUnit
) to allow for the use of a TreeMap<ComparableUnit<Q>, Quantity<Q>>
to allow for sorting by unit? I'm not sure if something like this would be feasible, as I'm still trying to wrap my head around the design and what can (and cannot) be changed at this point. For something like that to work, I reckon the following would have to be added to ComparableQuantity
:
@Override
ComparableUnit<Q> getUnit();
I may also just be misunderstanding this, but I'm sure we could group quantities together first by their unit and order passed to CompoundQuantity
, and then decompose groups of convertible units into their smallest respective units.
from indriya.
This draft is part of either option A) or B). And even if the list was reconciled with just 2, the current option C) has the most votes. If we go for that, there would be neither CompoundUnit
nor CompoundQuantity
.
from indriya.
Understandable. Assuming option C) maintains the most votes, do we have an idea of how the implementations of QuantityFormat
(I believe this has been renamed to AbstractQuantityFormat
) will format compound quantities? If it's just going to be a utility method that accepts a variable amount of Quantity<Q>
or ComparableQuantity<Q>
, then I could create drafts for each implementation.
from indriya.
Yes, QuantityFormat
is in the API now, just resolving #23 to implement that here. I am not sure, if there's enough evidence on how to do it without modelling the compound values, but e.g. @desruisseaux said they did something like it in SIS with AngleFormat That is just a single quantity, so hard to say if the approach would be versatile enough, but have a look at it if you can.
from indriya.
Would there be cases where one wants to handle something like 1m 3ft
? And would you in that case also want 1m 3ft + 2m 4ft = 3m 7ft
?
from indriya.
I am not sure, if operations like add()
properly work for a CompoundQuantity
like it does for Quantity
(aka implementing Quantity
) but I'd be open to that. If so, then the addition would indeed have to loop over each set and sum up exact matches into a new CompoundQuantity
.
from indriya.
The problem is, that of Quantity
at least getUnit
and getValue
don't make sense, but instead plurals like getUnits
or (not there, but it might also exist) getValue
are needed.
from indriya.
@jhg023 @filipvanlaenen @desruisseaux @otaviojava @ejberry @dautelle @duckAsteroid / all,
We should really get to some conclusion here (otherwise while there is still approx. 1y max till 2.0 has to go final, it may risk being descoped and postponed to a future version)
At the moment option C (no model objects, just using UnitFormat
and/or QuantityFormat
implementations) has a majority followed by A with half the votes of C and B (if you count all + and -) with -1.
I showed a quick draft of how A could work especially when it comes to storing fractions of a Quantity
. But while JSR 310 does both in different areas, the DateTimeFormatter or its predecessors like SimpleDateFormat show, how a SimpleQuantityFormat
(or another concrete class) could do this here, too.
The patterns have to be much more generic because it deals with more than just Time
, but patterns like "MM, mm"
(M=Major, m=minor) or "MM. m."
could format 76 in
. into 6 ft. 4 in.
Of course it would require additional information. If we were to use the old and new Date/Time formatter as inspiration, then something similar as a DateTimeFormatterBuilder may help. Allowing to do something like withMinimalUnit(INCH)
, setMajor(METRE)
or similar.
Would any of you like to take the lead on that and create a PoC? Either we create a dedicated feature branch or you could fork it in your own branch and propose a PR.
TIA,
Werner
from indriya.
There have been several branches in uom-se, so after merging #47, let's create two branches, one for option A which is fully functional (the support by QuantityFormat still could be improved, but it works like JSR 275/JScience did) already. Another one for Option C something like "quantityformat_only" or similar. All relevant classes will be removed from the master branch till either of them produce a satisfactory approach that can be merged back.
from indriya.
Dear @unitsofmeasurement/experts, @unitsofmeasurement/contributors,
I recreated the 2 feature-branches:
- https://github.com/unitsofmeasurement/indriya/tree/compound_unit_and_quantity
- https://github.com/unitsofmeasurement/indriya/tree/compound_format_only
for option A and C (which have a majority of votes each) in this ticket.
@andi-huber You joined a bit later but were extremely helpful and active, do you also have an opinion or preference here? The vote is close with just 1 more in favor of C compared to A. Each of these branches contains the necessary additions like CompoundUnit
, CompoundQuantity
or additions like a pattern (similar to JDK SimpleDateFormat
) in the SimpleQuantityFormat
. A could even use some of that as well, but especially if a majority wanted to go without those extra API or RI elements then please let's explore how QuantityFormat
could do this in similar ways as DateFormat
.
This is probably beyond he EDR but let's see how far we get with either approach.
from indriya.
@keilw thanks!
Quick answer for now:
I believe that option A) adds to the complexity of handling Unit composition, simplification and check for equality, but I might be wrong.
From a user's perspective, if there's any advantage of having option A) over option C) then there is at least a point to consider adding complexity.
Please give me a few days to investigate this.
from indriya.
@andi-huber Thanks for the update and checking out the options. I am not entirely sure if a CompoundUnit
is necessary but experience, maybe also mistakes by JSR 310 added the necessity of the TemporalAmount
(which is more like a CompoundQuantity
or QuantityAmount
if you want) Except for certain aspects of rendering, the CompoundUnit
likely adds less value than being able to exactly assign how many feet, inch or metre you want in a particular compound value. If everyone who is able to contribute to a solution thinks a pattern in QuantityFormat
is sufficient to decompose a value like 185 cm
into e.g. feet
and inches
, why not, but it may require a rather complex chain of conversions and converters to get there as well.
from indriya.
P.s.: For Indriya I added individual write access for @andi-huber and @filipvanlaenen (EG members normally have) so it's easier to work on these feature branches. Please use it with care and coordinate any push to master first or do a PR, but for the feature-branch it's fine to work there directly instead of your own local forks.
from indriya.
I started work on the 'Unit equivalence problem', that is to decide whether 2 compositions of UnitConverters are equivalent.
The only way I see to solve this, is to have unit composition mechanics produce a so called 'normal-form', which involves reordering, simplification and canceling out of UnitConverters within a sequence of UnitConverters that constitute the composed converter transformation.
eg add(3) ○ add(-3)
should cancel out to the identity transformation
Here's my conclusion:
I believe doing Unit composition with proposed 'compounds' (Option A) can get very complicated, there is a lot of undefined behavior regarding composition of 'formats'.
In contrast providing a solution that just uses formatters (Option C) that get applied at the end of an arbitrary complex quantity computation, seems way easier to implement. Also this is straight forward from a user's perspective, (s)he would not have to consult java-doc for every composition step they want to make.
I'm voting C)
from indriya.
... I also believe, that all 'compound ideas' could be translated and reused eg for a 'compound format builder'
from indriya.
Thanks for voting and your thoughts on the matter. Would you be able to start something in the "format-only" branch?
I got some pretty good results to format a CompoundQuantity
in the other branch while CompoundUnit
seems of very little use. However parsing is the real tricky beast in both cases.
E.g. if the concept of a "Compound.." something is completely abandoned, then the only option for QuantityFormat
is to parse the result of say 5ft 10in
or 2mi, 10km, 50mm
back into a single Quantity
.
from indriya.
Is it possible to translate existing
ONE_HPA = Quantities.getQuantity(BigDecimal.ONE, HECTO(PASCAL));
TEN_PA = Quantities.getQuantity(BigDecimal.TEN, PASCAL);
pressures = new CompoundQuantity<>(ONE_HPA, TEN_PA);
assertEquals("1 hPa 10 Pa", pressures.toString());
into something like ...
ONE_HPA = Quantities.getQuantity(BigDecimal.ONE, HECTO(PASCAL));
TEN_PA = Quantities.getQuantity(BigDecimal.TEN, PASCAL);
formatter = CompoundFormat.of(HECTO(PASCAL), PASCAL);
sum = ONE_HPA.add(TEN_PA);
assertEquals("1 hPa 10 Pa", formatter.format(sum));
from indriya.
If a specialized QuantityFormat
(CompoundQuantity is currently not an API element and it may be fine to stay in the RI or its own SPI like we did with Range
or Measurement
) had to store Quantity
information then what complexity would that safe? Either a QuantityFormat
implementation or some kind of "builder" should be able to format it with just a couple of "hints", not having to store the actual Quantity
array, because if that is the only way to accomplish it, then option A with a compound model offers a transparent way of handling the quantity array or individual elements like e.g. TemporalAmount
.
from indriya.
As suggested above, the 'formatter' would store Unit information, not Quantity information.
from indriya.
Ok then it's closer to @dautelle's preference of B whether you call it CompoundUnit
or not (if we find the construct helpful, why not explore that as well) So please check out https://github.com/unitsofmeasurement/indriya/tree/compound_format_only and let's work on a solution there.
from indriya.
Related Issues (20)
- Add ability to remove label from `SimpleUnitFormat` HOT 2
- indriya 2.1.3 depends on two versions of javax.measure:unit-api
- Create Java 9+ version of Calculus
- Release Indriya 2.2
- Release 2.2 missing on Maven central HOT 2
- Turn Range into an Interface
- Support interoperability to other unit systems HOT 15
- Allow to create a standard SymbolMap for EBNF
- EBNFUnitFormat can not handle chain of TransformedUnit HOT 4
- Lazy reduces scalability of applications using Indriya HOT 1
- Turn QuantityRange into a record for Java 17+
- Missing symbol for some derived units HOT 2
- Change internals of SimpleUnitFormat
- Create a "SymbolMapUnitFormat" abstraction over EBNF and LocalUnitFormat
- Adding a Pattern to SimpleUnitFormat similar to SimpleQuantityFormat or SimpleDateFormat
- Parsing of 1/mile is not possible HOT 1
- EBNFUnitFormat formats into a string that it cannot parse back anymore HOT 2
- Overflow or underflow happening for simple addition? HOT 7
- Correct JavaDoc for ComparableQuantity
- Scaling / multiplication is unable to apply factors to temperatures HOT 10
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from indriya.