Skip to content

runtime: map[float/complex] uses incorrect comparison #2609

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

Closed
ianlancetaylor opened this issue Dec 23, 2011 · 4 comments
Closed

runtime: map[float/complex] uses incorrect comparison #2609

ianlancetaylor opened this issue Dec 23, 2011 · 4 comments
Milestone

Comments

@ianlancetaylor
Copy link
Contributor

package main

var m = make(map[float64]bool)

var f float64 = 0

func main() {
    m[f] = true
    if f == -f {
        println("equal")
    } else {
        println("not equal")
    }
    if _, found := m[-f]; found {
        println("found")
    } else {
        println("not found")
    }
}

This program prints

equal
not found

That is wrong.  If two map key values are ==, then they should have the same value in a
map.

This general problem applies to maps with key types float32, float64, complex64,
complex128.  The current map code winds up comparing values using memcmp, but it has to
use the appropriate floating point equality operator.
@cznic
Copy link
Contributor

cznic commented Dec 31, 2011

Comment 1:

Interesting issue. I suggest (weakly) to keep it as it is, though note it well in the
docs/specs. The proposed reason to keep it is the difference between the
arithmetic/algebraic and set operations involved. In the finite set of floating/complex
numbers represented in N bits, the used encoding has(IEE754?)/may have distinct values
for +0 and -0 (involved int the key set operation of a map). The equality a == b checks
for a root of y = a - b (is a - b == 0?). In its way both differing cases make sense to
me.
From the practice POV, float/complex map keys are probably not that common and as one
has to already think about rounding errors/impreciseness, adding
Abs(myFloatOrComplexKey) can help where the +0 and -0 should not be seen as distinct -
while having the same nice property where it could in theory make perfect sense (no
example at hand).
A side note. The memcmp involved possibly introduces other issues:
- Can denormalized fp/cmplx values occur in Go? If so, the values of a key set for a map
can have more members than distinct numbers representable.
- NaN is commonly not equal to anything, including itself. Due to memcmp, a NaN key may
surprisingly return a previously stored value from a map. This can be used as an ugly
hack but also as an useful thing in modeling something with a map[R/C]T.
- IIRC, there is more than one concrete bit pattern for NaNs.
- Items I can't recall now.
Thoughts?

@ianlancetaylor
Copy link
Contributor Author

Comment 2:

Right, 0 vs. -0 is just one case.  There are multiple representations for both positive
and negative infinity, and for NaNs.  Go does permit denormalized numbers but I don't
think that affects this issue.
I don't think it is possible to justify having two key values that are == not return the
same value in a map.  Go doesn't have any notion of "different bit pattern but ==", and
I can't see any good reason to introduce one.

@robpike
Copy link
Contributor

robpike commented Jan 13, 2012

Comment 3:

Owner changed to [email protected].

@rsc
Copy link
Contributor

rsc commented Jan 26, 2012

Comment 5:

This issue was closed by revision 408f0b1.

Status changed to Fixed.

@rsc rsc added this to the Go1 milestone Apr 10, 2015
@rsc rsc removed the priority-go1 label Apr 10, 2015
@golang golang locked and limited conversation to collaborators Jun 24, 2016
This issue was closed.
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

5 participants