-
-
Notifications
You must be signed in to change notification settings - Fork 42
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
Incorrect equality determination #384
Comments
Thanks for bringing that to our attention.
Shows that @andi-huber Any idea how this could be improved? IMO casting to |
Agreed, the root seems to be the handling of decimal values and don't have issues with integers. I have another issue where adding quantities with decimals ends up with less than one of the numbers being added, but haven't been able to replicate simply for an example and might be a separate issue |
Checking number equality can only be answered within margins of numerical errors, hence I don't recommend using Java |
Eg. see how to properly check number equality with JUnit ... https://junit.org/junit5/docs/5.0.1/api/org/junit/jupiter/api/Assertions.html#assertEquals-double-double-double-. (Note the |
As for improvements for Indriya in that regard, (as I believe I said before) we could honor such a |
Without change of API, this could also be done with a utility class, that provides some static methods for this. |
If someone wants to jump in and work on such a utility, I'd be happy to review pull requests. |
It seems the bug lies mainly in l 433-436 of DefaultNumberSystem:
For a @andi-huber Any chance to handle Zero differently or is there a bigger problem with that class? |
what bug? |
Creating an unnecessary |
Well, I do not agree: If the |
At least 0.0 is special because it has no value regardless of being The mentioned "utility class" won't help if the value types are different, at most we could try to disect it and use e.g. the |
Would it make sense to normalize the internal implementation to always use BigDecimal? Would cover any need of operations without having this complexity. |
I'm not sure, it would blow up memory consumption and likely slow everything down a bit. The special case of 0.0 failing the modulo check is easy to catch and it'll solve this particular problem. |
I added a Zero-check to the latest snappshot, but apparently, the "Lambda Magic" in L101 of ScaleHelper turns two |
Actually it comes back to DefaultNumberSystem where additions always result in a Regarding the suggestion by @GregJohnStewart to handle everything as |
The problem was fixed in the SNAPSHOT, @GregJohnStewart could you try it out? |
To be clear, are you asking I pull the project down and publish the latest locally, or? (I don't see a snapshot on Maven) |
It may be good to refresh the local SNAPSHOT but you should not need to build it yourself, because indriya 285 deployed the latest snapshot on the Sonatype Snapshot repo. The "basic" demos use the 2.1.4-SNAPSHOT and QuantityDemo shows the two are equal now with the latest snapshot. If you try to switch back to e.g. 2.1.3 they are not. |
Since there were no contesting statements, I assume this is fixed. |
First off, apologies for how long it took me to circle back to this. With the For example:
(Was appropriately Looks like a fix here broke other places |
I'll note that a Another of note:
It still appears these issues are strictly dealing with floating point arithmetic, and integer operations are clear. Let me know if I can provide anything else, any context, etc. If a working/storming session session would help, I'm open to it |
This looks weird, but how can one reproduce those? PRs like #388 might be somehow related, but have to investigate based on test code to reproduce. |
Quantity<?> result = Quantities.getQuantity(0.0, unit);//.add(Quantities.getQuantity(0.0, Units.MOLE));
assertEquals(
Quantities.getQuantity(0, unit),
result
); Results:
Though will note that apparently this probably follows a convention of Loos like the It appears that numbers are thrown off when using derived units ( Unit WATT_HOURS = UnitTools.getUnitWithNameSymbol(
Units.WATT.multiply(Units.HOUR),
"Watt-Hour",
"Wh"
);
Unit unit = UnitTools.getUnitWithNameSymbol(
WATT_HOURS.divide(1_000),
"Milliwatt-Hour",
"mWh"
);
assertEquals(
Quantities.getQuantity(0.0, unit).add(Quantities.getQuantity(1.1, unit)),
Quantities.getQuantity(1.1, unit)
); Results:
|
Glad that big difference could be clarified. I added a simplified code (without the UnitTools but otherwise quite similar) into QuantityDemo and using Indriya 2.1.3 the only difference is, the first comparison
remains false while the 2.1.4-SNAPSHOT considers them as equal. So it works for a And yes, the PR #388 caused some serious problems, @andi-huber did you test it locally before merging or after??? |
Reopening this, because it works now (after 2.1.4) for base units, but still fails for most others despite an identical numeric type like Quantity q1 = Quantities.getQuantity(0.0, Units.MOLE).add(Quantities.getQuantity(1.1, Units.MOLE));
Quantity q2 = Quantities.getQuantity(1.1, Units.MOLE);
System.out.println(q1.equals(q2)); works, returning final Unit<Energy> UNIT_WATT_HOUR = Units.WATT.multiply(Units.HOUR).asType(Energy.class);
Quantity q3 = Quantities.getQuantity(0.0, UNIT_WATT_HOUR).add(Quantities.getQuantity(1.1, UNIT_WATT_HOUR));
Quantity q4 = Quantities.getQuantity(1.1, UNIT_WATT_HOUR);
System.out.println(q3.equals(q4)); returns While it seems to work properly for base units, the method @andi-huber Any ideas? |
Seems
Is the problem. It converts everything to system units except base units, therefore even cases where both units are identical face an unnecessary conversion of the unit. And transformation of the number. |
I tried to bypass this for identical units, but frankly I'm out of options here because it breaks precisely those special cases like Any unit other than BaseUnit results in a converted result where the value is a value RationalNumber and therefore different from any other Number type. final Unit<Energy> UNIT_WATT_HOUR = Units.WATT.multiply(Units.HOUR).asType(Energy.class);
Quantity<?> q5 = Quantities.getQuantity(BigDecimal.ZERO, UNIT_WATT_HOUR).add(Quantities.getQuantity(BigDecimal.valueOf(1.1), UNIT_WATT_HOUR));
Quantity<?> q6 = Quantities.getQuantity(RationalNumber.of(1.1), UNIT_WATT_HOUR);
System.out.println(q5.equals(q6)); This is |
With the following code:
which results in the following error:
AssertionFailedError: expected: tech.units.indriya.quantity.NumberQuantity@30f99ca1<1.1 mol> but was: tech.units.indriya.quantity.NumberQuantity@edb8f0c<1.1 mol>
Any thoughts?
Additionally,
is fine...
The text was updated successfully, but these errors were encountered: