java - How can I effectively use floats in equals()? -
i have following immutable hsl class use represent colour , aide in calculations on rgba colours little more finesse.
public class hsl { protected final float hue; protected final float saturation; protected final float lightness; public hsl(float hue, float saturation, float lightness) { this.hue = hue; this.saturation = saturation; this.lightness = lightness; } // [snip] removed calculation helper functions @override public string tostring() { return "hsl(" + hue + ", " + saturation + ", " + lightness + ")"; } @override public int hashcode() { return 37 * float.floattointbits(hue) + 37 * float.floattointbits(saturation) + 37 * float.floattointbits(lightness); } @override public boolean equals(object o) { if (o == null || !(o instanceof hsl)) { return false; } hsl hsl = (hsl)o; // we're worried 4 decimal places of accuracy. that's more 24b rgb space can represent anyway. return math.abs(this.hue - hsl.hue) < 0.0001f && math.abs(this.lightness - hsl.lightness) < 0.0001f && math.abs(this.saturation - hsl.saturation) < 0.0001f; } }
while don't foresee using particular class in hashmap
or similar it's intermediary between similar rgba
class uses int
s it's internal storage, i'm concerned general case of using floats in equality. can make epsilon comparison small, , if make arbitrarily small there many float
values can represented internally in multiple ways leading different values returned float.floattointbits
. best way around this? or not issue in reality , i'm overthinking things?
the other answers great job of explaining why current design may cause problems. rather repeat that, i'll propose solution.
if care accuracy number of decimal places (it appears 4), multiply incoming float
values 10,000 , manage them long
values. equality , hashcode calculations exact.
i assume you've omitted getters class brevity. if so, ensure javadocs explain loss of precision occur when passing float
class constructor , retrieving getter.
Comments
Post a Comment