On 4/15/14, 5:19 AM, Gilles wrote: > On Tue, 15 Apr 2014 08:03:51 +0900, Cyrille Artho wrote: >> Dear all, >> Java's default contract (in Object) states that two objects with >> equal data should return the same hashCode. In other words, if >> a.equals(b), their return value of hashCode() must be the same. >> >> Unfortunately, with Double values, new Double(0.0d).equals(new >> Double(-0.0d)) is false. This is because their internal >> representation >> differs. Java's built-in Double thus returns a different hashCode >> for >> 0.0d and -0.0d. >> >> However, Apache's math library uses a mathematical comparison for >> Complex/Dfp (perhaps also others), where 0.0d == -0.0d. This breaks >> the contract, and thus causes problems when Complex or Dfp instances >> are used in containers such as HashMap, HashSet, etc. See the bug >> report for more details and test cases: >> >> https://issues.apache.org/jira/browse/MATH-1118 >> >> It is not quite clear how this should be fixed. Gilles posted a >> patch >> that uses Java's equals to perform the comparison. This fixes the >> behavior w.r.t. the contract but may surprise people who expect a >> mathematical comparison. >> >> Another possible fix (without a tentative patch at this time) would >> be to change hashCode: >> >> public int hashCode() { >> if (imaginary == 0.0d && real == 0.0d) { >> return ZERO.hashCode(); >> } >> ... >> >> and similar for Dfp. >> >> This fixes the issue for zero values. However, there may be issues >> with normalized vs. unnormalized floating point values with the same >> (mathematical) value but different internal representations, where >> this kind of fix cannot be used. I'm not familiar enough with >> various >> floating point implementations to know if Java always normalizes the >> values before using them in a statement like hashCode(). >> >> Therefore, the suggestion above is mathematically nice for +/- 0.0d, >> but otherwise much less safe than Gilles' patch. >> >> Any comments? Probably best post them on JIRA: >> >> https://issues.apache.org/jira/browse/MATH-1118 > > IIUC, fixing the "hashCode" method as above would not solve the > problem > since it deals only with "0" whereas the unit test fails for "-i".
Thanks. I get that now. > > Do we agree that we first have to decide whether "Complex" should > behave > as "Double"? > > If the answer is "no" (as is the case now), shouldn't we document > that > "hash tables will not operate properly" (cf. Javadoc for "Double")? > And is this behaviour acceptable? I don't think having equal instances hashing to different values is acceptable. We have to do something to fix that. > > One possibility is to have the "equals(Complex)" behave according to > the JDK semantics, and add a static method "equals(Complex, Complex)" > that would implement mathematical comparison (where "-0" == "0"). I like the idea of imitating the way Double works for equals. Phil > > > Regards, > Gilles > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org > For additional commands, e-mail: dev-h...@commons.apache.org > > --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org For additional commands, e-mail: dev-h...@commons.apache.org