Skip to content
This repository has been archived by the owner on May 26, 2021. It is now read-only.

Same Units considered different #164

Closed
keilw opened this issue Jun 19, 2017 · 5 comments
Closed

Same Units considered different #164

keilw opened this issue Jun 19, 2017 · 5 comments
Assignees
Milestone

Comments

@keilw
Copy link
Member

keilw commented Jun 19, 2017

Similar to #156 for quantities

assertEquals(MICRO(GRAM), GRAM.divide(1000000));

works, but using nested operations

assertEquals(MICRO(GRAM), GRAM.divide(1000).divide(1000));

fails. Despite two divisions by 1k have the same result as dividing by 1 Mio.

@keilw
Copy link
Member Author

keilw commented Jun 19, 2017

Somewhat related to unitsofmeasurement/uom-systems#108. A solution for this issue could benefit unitsofmeasurement/uom-systems#108 for UCUM or other systems.

@keilw
Copy link
Member Author

keilw commented Aug 4, 2017

The solution for unitsofmeasurement/uom-systems#111 looks helpful as it results e.g. for UCUM.LITER and UCUM.LITER_DM3 in equal converters.

Under the assumption, that if unit1.getConverterTo(unit2).equals(unit2.getConverterTo(unit1) it should be possible to add such fallback to all cases not yet covered by particular unit types. E.g. whenever the concrete implementations of unit1 and unit2 are different.

@keilw
Copy link
Member Author

keilw commented Aug 8, 2017

AbstractUnit uses equals() a lot internally comparing units to another, especially when you call something like unit1.getConverterTo(unit2).equals(unit2.getConverterTo(unit1). Therefore using it to assist e.g. unit1.equals(unit2) is impossible because it leads to an infinite circular call and StackOverflowException. Taking equals() out of all these methods does not look feasible either, it makes them work as they do.

There are API specific methods like isCompatible(Unit<?> that) so at the moment the only reliable solution is adding public boolean isEquivalentOf(Unit<Q> that) similar to the one already offered by ComparableQuantity. Although a certain combination of operations may be considered "equal" the result should always by definition be "equivalent". https://english.stackexchange.com/questions/317782/equal-vs-equivalent-finer-differences-in-meaning-and-usage-in-4-distinct-scena/317792 provides good answers to how they differ. And AbstractUnit already states, all conversions between physical units should be symmetric. Therefore the results are equivalent, but not necessarily equal.
The JDK standard method clone() is described in a similar way:
http://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#clone%28%29

While it is typically the case that:
x.clone().equals(x)
will be true, this is not an absolute requirement.

Certain units like UCUM.TONNE are a similar example. It should be equal to Units.KILOGRAM.multiply(1000) but comparing it to certain other Mass operations there's no guarantee, the exact Unit implementations are going to be the same. And Integer.valueOf(1) is never equal to BigInteger.valueOf(1) or Double.valueOf(1) either, although they are all equivalent.

@andi-huber
Copy link
Member

Other than testing, what are good use-cases why someone would want to check, whether 2 Units are equal?

My point is:
If its hard to specify what we mean by 2 Units are equal, then its also hard for users to understand. So why do we try to implement such functionality?

@keilw
Copy link
Member Author

keilw commented Apr 19, 2018

This came out of issues and questions on the UCUM front in the unit-systems modules. isEquivalentTo() right now it may still be wrongly named isEquivalentOf() (at least I think To was the preference) exists and works. I hope some changes in the structure of UnitConverter implementations won't break that, but the way to check are mainly things like if X.getConverterTo(Y) = Y.getConverterTo(X) then they are equivalent, even though the stricter equals() method would usuallly fail.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants