Skip to content

math: add Compare and Compare32 #56491

Closed
Closed
@zhangyunhao116

Description

@zhangyunhao116

The slices.Sort doesn't support sorting slices of floating-point numbers containing Not-a-number (NaN) values, It's not very intuitive.

Once the slices package is merged into stdlib, the sort.{TYPE}s(e.g. sort.Ints, sort.Float64s) APIs may be semi-deprecated. But the slices package doesn't provide a simple way to sort slices of floats containing NaNs, it recommends using slices.SortFunc(x, func(a, b float64) bool {return a < b || (math.IsNaN(a) && !math.IsNaN(b))}), this function is very complex compared to using sort.Float64s.

Related CL: https://go-review.googlesource.com/c/exp/+/446155

Activity

added this to the Proposal milestone on Oct 31, 2022
gopherbot

gopherbot commented on Oct 31, 2022

@gopherbot
Contributor

Change https://go.dev/cl/446155 mentions this issue: slices: Sort support sorting slices of floating-point numbers containing NaN values

dsnet

dsnet commented on Oct 31, 2022

@dsnet
Member

This is related to #33440. @smasher164 mentions the existence of a total-ordering predicate that could be used to sort floats with NaNs.

moved this to Incoming in Proposalson Oct 31, 2022
ianlancetaylor

ianlancetaylor commented on Oct 31, 2022

@ianlancetaylor
Contributor
randall77

randall77 commented on Oct 31, 2022

@randall77
Contributor

Once the slices package is merged into stdlib, the sort.{TYPE}s(e.g. sort.Ints, sort.Float64s) APIs may be semi-deprecated.

I don't think they will, using sort.Float64s will be fine forever.

I think the only advantage of slices.Sort is that it will work on slices of named float64s (e.g. type F float64; a := []F{5,4,3}; slices.Sort(a), that won't work using sort.Float64s). And in that rare case one can use the described workaround.

zhangyunhao116

zhangyunhao116 commented on Nov 1, 2022

@zhangyunhao116
ContributorAuthor

Since Go1.18 is released, many users use the slices.Sort to replace sort.{TYPE}s, because the former is faster and more clear in almost all cases. From the point of view of the users, the former looks more like a replacement of the latter, they have almost the same function in fact except the slices.Sort doesn't support sorting slices containing NaNs.

The main concern is that users don't notice this special case, and the replacement may break their codes.

earthboundkid

earthboundkid commented on Nov 2, 2022

@earthboundkid
Contributor

I think it's worth adding documentation to slices.Sort that sorting a float won't work. Maybe also there could be a comparator function in sort.

eliben

eliben commented on Nov 2, 2022

@eliben
Member

I think it's worth adding documentation to slices.Sort that sorting a float won't work. Maybe also there could be a comparator function in sort.

The documentation for Sort is currently:

Sort sorts a slice of any ordered type in ascending order. Sort may fail to sort correctly when sorting slices of floating-point numbers containing Not-a-number (NaN) values. Use slices.SortFunc(x, func(a, b float64) bool {return a < b || (math.IsNaN(a) && !math.IsNaN(b))}) instead if the input may contain NaNs.

Is this not sufficient documentation, @carlmjohnson ?

eliben

eliben commented on Nov 2, 2022

@eliben
Member

@zhangyunhao116 I'm not a big fan of this proposal at this time. The problem with sorting floats is clearly documented and a workaround is provided. It's easy to sort using SortFunc

earthboundkid

earthboundkid commented on Nov 2, 2022

@earthboundkid
Contributor

That seems good to me.

In #50340 I think there was talk about adding sort.Compare which would take a comparable and return -1, 0, 1. If something like that is ever added there should also be CompareFloat, but it's not necessary on its own.

zhangyunhao116

zhangyunhao116 commented on Nov 4, 2022

@zhangyunhao116
ContributorAuthor

The problem with sorting floats is clearly documented and a workaround is provided. It's easy to sort using SortFunc

Agree that the special case is clearly documented and has a workaround, but it's nice to support all the special cases as sort.{TYPE}s does :)

I did a simple poll about slices.Sort at my work. The question is

The slices.Sort sorts a slice of any ordered type in ascending order. Intuitively, you think the function is

A. A replacement of sort.{TYPE}s APIs, has the same output, and support all special cases.
B. slices.Sort and sort.{TYPE}s APIs exist side by side, and they may have different outputs in special cases.

51 people joined it, 82.4% (42) selected A, and 17.6% (9) selected B. Looks like many users of this API doesn't notice the special case.

zhangyunhao116

zhangyunhao116 commented on Nov 4, 2022

@zhangyunhao116
ContributorAuthor

The proposal still need more discussions, it's a rare case, and It's merely not as users intuitively expected. The slices.Sort work very well for all the general cases.

63 remaining items

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @rsc@earthboundkid@eliben@xen0n@dmitshur

        Issue actions

          math: add Compare and Compare32 · Issue #56491 · golang/go