Why does the comparison function given to qsort() need to return three different values?
I have read that the comparison function required by qsort()
needs to have 3 outcomes:
- a negative result if
val1 < val2
0
ifval1 == val2
- a positive result if
val1 > val2
As far as I know, sorting an array only requires a predicate that returns true or false. Take bubble sort for example:
int compare(int a, int b)
{
if(a>b) return 1;
return 0;
}
void bubbleSort(int arr, int n)
{
int i, j;
for (i = 0; i < n-1; i++)
for (j = 0; j < n-i-1; j++)
if ( compare(arr[j],arr[j+1]) )
swap(&arr[j], &arr[j+1]);
}
So why does the qsort()
comparison function need to have 3 possible outcomes and not 2?
c algorithm sorting
add a comment |
I have read that the comparison function required by qsort()
needs to have 3 outcomes:
- a negative result if
val1 < val2
0
ifval1 == val2
- a positive result if
val1 > val2
As far as I know, sorting an array only requires a predicate that returns true or false. Take bubble sort for example:
int compare(int a, int b)
{
if(a>b) return 1;
return 0;
}
void bubbleSort(int arr, int n)
{
int i, j;
for (i = 0; i < n-1; i++)
for (j = 0; j < n-i-1; j++)
if ( compare(arr[j],arr[j+1]) )
swap(&arr[j], &arr[j+1]);
}
So why does the qsort()
comparison function need to have 3 possible outcomes and not 2?
c algorithm sorting
1
IMO, this is related to the bad habit to perform binary searches as ternary searches, with early termination in case of equality. In most cases, this is counter-productive.
– Yves Daoust
Dec 15 '18 at 11:52
add a comment |
I have read that the comparison function required by qsort()
needs to have 3 outcomes:
- a negative result if
val1 < val2
0
ifval1 == val2
- a positive result if
val1 > val2
As far as I know, sorting an array only requires a predicate that returns true or false. Take bubble sort for example:
int compare(int a, int b)
{
if(a>b) return 1;
return 0;
}
void bubbleSort(int arr, int n)
{
int i, j;
for (i = 0; i < n-1; i++)
for (j = 0; j < n-i-1; j++)
if ( compare(arr[j],arr[j+1]) )
swap(&arr[j], &arr[j+1]);
}
So why does the qsort()
comparison function need to have 3 possible outcomes and not 2?
c algorithm sorting
I have read that the comparison function required by qsort()
needs to have 3 outcomes:
- a negative result if
val1 < val2
0
ifval1 == val2
- a positive result if
val1 > val2
As far as I know, sorting an array only requires a predicate that returns true or false. Take bubble sort for example:
int compare(int a, int b)
{
if(a>b) return 1;
return 0;
}
void bubbleSort(int arr, int n)
{
int i, j;
for (i = 0; i < n-1; i++)
for (j = 0; j < n-i-1; j++)
if ( compare(arr[j],arr[j+1]) )
swap(&arr[j], &arr[j+1]);
}
So why does the qsort()
comparison function need to have 3 possible outcomes and not 2?
c algorithm sorting
c algorithm sorting
edited Dec 16 '18 at 6:08
isanae
2,50111336
2,50111336
asked Dec 15 '18 at 11:06
MihaiMMihaiM
554
554
1
IMO, this is related to the bad habit to perform binary searches as ternary searches, with early termination in case of equality. In most cases, this is counter-productive.
– Yves Daoust
Dec 15 '18 at 11:52
add a comment |
1
IMO, this is related to the bad habit to perform binary searches as ternary searches, with early termination in case of equality. In most cases, this is counter-productive.
– Yves Daoust
Dec 15 '18 at 11:52
1
1
IMO, this is related to the bad habit to perform binary searches as ternary searches, with early termination in case of equality. In most cases, this is counter-productive.
– Yves Daoust
Dec 15 '18 at 11:52
IMO, this is related to the bad habit to perform binary searches as ternary searches, with early termination in case of equality. In most cases, this is counter-productive.
– Yves Daoust
Dec 15 '18 at 11:52
add a comment |
5 Answers
5
active
oldest
votes
Based on the comment of @Matteo Italia, there is an efficiency issue in the number of comparison and you can reduce the number of comparison using the equality as a == b
and !(a < b) && !(b < a)
are equivalent in some cases (for example when the values are integer).
Also, in more general case (not in qsort specifically as mentioned in comments), you need it for stability of the sort function. In equality cases, if the sort wants to be stable, it should know about the equality in the comparison. You can know more about the stabilty in sorting here.
Hence, three value return is required for stable sort methods.
It must be noted that (1)qsort
is not stable and (2) it's not strictly required, but just an optimization - if you only have a "less than" operator, you can deduce the equality by using two comparisons (a == b
<->!(a < b) && !(b < a)
).
– Matteo Italia
Dec 15 '18 at 11:26
1
@MatteoItalia(a == b <-> !(a < b) && !(b < a))
is not certainly true whena,b
are floating point and a value may be not-a-number.
– chux
Dec 15 '18 at 16:08
2
qsort()
is not specified to be stable.
– chux
Dec 15 '18 at 16:10
2
A 3-way sort is pretty much required for a stable sort. While technically correct, it's not really relevant to a discussion why withqsort()
, "is it really necessary?".
– chux
Dec 15 '18 at 18:11
1
True, The relevancy of requirements of a 3-way sort are a good point for OP to explore - just like the issues of(a == b <-> !(a < b) && !(b < a))
with FP math are good point to explore with sorting.
– chux
Dec 15 '18 at 18:21
|
show 3 more comments
qsort
could be written using a boolean compare function instead of a three-way compare but the specification says that it takes a three-way compare function and some (not all) implementations take advantage of the three possible cases. If your compare function doesn't conform to the specification, Undefined Behaviour will result. In this case, Undefined Behaviour might include a failure to sort correctly or a buffer overrun triggered on very rare corner cases, which you might not notice until the space shuttle is returning from orbit. So don't do that.
As to why an implementation might want the three-way comparison, here is one possibility: for inputs with a lot of repeated values, quicksort can be speeded up considerably by using a three-way partition. That can be done with a two-way comparison by doing the comparison twice in opposite directions, but an implementor, knowing that a three-way comparator is required, is likely to test for equality when that's what they want to know.
add a comment |
If element A ==
element B but the comparator function tells qsort
that B > A
then qsort
will think there may be other elements which should be between A
and B
when that is not the case, and therefore perform unnecessary checks.
add a comment |
Technically, you can do with just less-than, because a == b
is equivalent to !(a < b) && !(b < a)
.
1
Independently of Matteo's comment. ;-)
– Yves Daoust
Dec 15 '18 at 11:36
2
That is, assuming full ordering. Seems obvious as we are sorting, but it's important to remember that equivalence does not hold in the general case.
– spectras
Dec 15 '18 at 11:37
2
@yves: if at least one ofa
andb
is NaN, all comparisons returnfalse
. But!false && !false
istrue
.
– rici
Dec 15 '18 at 17:38
3
@yvesDaoust: So was the Boer War, but there it is. (ambiguously signedchar
is way ahead on my list :-)
– rici
Dec 15 '18 at 18:53
2
@YvesDaoust, comparison returning NaN? How would that work? If you didif (a < b)
andb
happened to be NaN, the program would still need to decide if it should run the conditional block or not...
– ilkkachu
Dec 15 '18 at 22:39
|
show 4 more comments
If the quicksort inner loop is written equivalent to this:
while(x[i] < pivot) i++; // less-than
while(pivot < x[j]) j--; // less-than
then you can get away with only implementing <
.
In any case, stick to the principle of least astonishment by making it more obvious what the caller is supposed to do -- if your compare function pointer is named compare
and the function shouldn't behave like a usual stdlib qsort
compare delegate, then it's a bad idea.
On the other hand, if your parameter is named something like less_than
or isLessThan
, it should be much more obvious to the caller what is expected from the comparison function:
void sort(
const void * arr,
size_t num_items,
size_t element_size,
bool (*is_less_than)(const void*, const void*)
);
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53791771%2fwhy-does-the-comparison-function-given-to-qsort-need-to-return-three-different%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
Based on the comment of @Matteo Italia, there is an efficiency issue in the number of comparison and you can reduce the number of comparison using the equality as a == b
and !(a < b) && !(b < a)
are equivalent in some cases (for example when the values are integer).
Also, in more general case (not in qsort specifically as mentioned in comments), you need it for stability of the sort function. In equality cases, if the sort wants to be stable, it should know about the equality in the comparison. You can know more about the stabilty in sorting here.
Hence, three value return is required for stable sort methods.
It must be noted that (1)qsort
is not stable and (2) it's not strictly required, but just an optimization - if you only have a "less than" operator, you can deduce the equality by using two comparisons (a == b
<->!(a < b) && !(b < a)
).
– Matteo Italia
Dec 15 '18 at 11:26
1
@MatteoItalia(a == b <-> !(a < b) && !(b < a))
is not certainly true whena,b
are floating point and a value may be not-a-number.
– chux
Dec 15 '18 at 16:08
2
qsort()
is not specified to be stable.
– chux
Dec 15 '18 at 16:10
2
A 3-way sort is pretty much required for a stable sort. While technically correct, it's not really relevant to a discussion why withqsort()
, "is it really necessary?".
– chux
Dec 15 '18 at 18:11
1
True, The relevancy of requirements of a 3-way sort are a good point for OP to explore - just like the issues of(a == b <-> !(a < b) && !(b < a))
with FP math are good point to explore with sorting.
– chux
Dec 15 '18 at 18:21
|
show 3 more comments
Based on the comment of @Matteo Italia, there is an efficiency issue in the number of comparison and you can reduce the number of comparison using the equality as a == b
and !(a < b) && !(b < a)
are equivalent in some cases (for example when the values are integer).
Also, in more general case (not in qsort specifically as mentioned in comments), you need it for stability of the sort function. In equality cases, if the sort wants to be stable, it should know about the equality in the comparison. You can know more about the stabilty in sorting here.
Hence, three value return is required for stable sort methods.
It must be noted that (1)qsort
is not stable and (2) it's not strictly required, but just an optimization - if you only have a "less than" operator, you can deduce the equality by using two comparisons (a == b
<->!(a < b) && !(b < a)
).
– Matteo Italia
Dec 15 '18 at 11:26
1
@MatteoItalia(a == b <-> !(a < b) && !(b < a))
is not certainly true whena,b
are floating point and a value may be not-a-number.
– chux
Dec 15 '18 at 16:08
2
qsort()
is not specified to be stable.
– chux
Dec 15 '18 at 16:10
2
A 3-way sort is pretty much required for a stable sort. While technically correct, it's not really relevant to a discussion why withqsort()
, "is it really necessary?".
– chux
Dec 15 '18 at 18:11
1
True, The relevancy of requirements of a 3-way sort are a good point for OP to explore - just like the issues of(a == b <-> !(a < b) && !(b < a))
with FP math are good point to explore with sorting.
– chux
Dec 15 '18 at 18:21
|
show 3 more comments
Based on the comment of @Matteo Italia, there is an efficiency issue in the number of comparison and you can reduce the number of comparison using the equality as a == b
and !(a < b) && !(b < a)
are equivalent in some cases (for example when the values are integer).
Also, in more general case (not in qsort specifically as mentioned in comments), you need it for stability of the sort function. In equality cases, if the sort wants to be stable, it should know about the equality in the comparison. You can know more about the stabilty in sorting here.
Hence, three value return is required for stable sort methods.
Based on the comment of @Matteo Italia, there is an efficiency issue in the number of comparison and you can reduce the number of comparison using the equality as a == b
and !(a < b) && !(b < a)
are equivalent in some cases (for example when the values are integer).
Also, in more general case (not in qsort specifically as mentioned in comments), you need it for stability of the sort function. In equality cases, if the sort wants to be stable, it should know about the equality in the comparison. You can know more about the stabilty in sorting here.
Hence, three value return is required for stable sort methods.
edited Dec 15 '18 at 16:34
answered Dec 15 '18 at 11:18
OmGOmG
7,97852743
7,97852743
It must be noted that (1)qsort
is not stable and (2) it's not strictly required, but just an optimization - if you only have a "less than" operator, you can deduce the equality by using two comparisons (a == b
<->!(a < b) && !(b < a)
).
– Matteo Italia
Dec 15 '18 at 11:26
1
@MatteoItalia(a == b <-> !(a < b) && !(b < a))
is not certainly true whena,b
are floating point and a value may be not-a-number.
– chux
Dec 15 '18 at 16:08
2
qsort()
is not specified to be stable.
– chux
Dec 15 '18 at 16:10
2
A 3-way sort is pretty much required for a stable sort. While technically correct, it's not really relevant to a discussion why withqsort()
, "is it really necessary?".
– chux
Dec 15 '18 at 18:11
1
True, The relevancy of requirements of a 3-way sort are a good point for OP to explore - just like the issues of(a == b <-> !(a < b) && !(b < a))
with FP math are good point to explore with sorting.
– chux
Dec 15 '18 at 18:21
|
show 3 more comments
It must be noted that (1)qsort
is not stable and (2) it's not strictly required, but just an optimization - if you only have a "less than" operator, you can deduce the equality by using two comparisons (a == b
<->!(a < b) && !(b < a)
).
– Matteo Italia
Dec 15 '18 at 11:26
1
@MatteoItalia(a == b <-> !(a < b) && !(b < a))
is not certainly true whena,b
are floating point and a value may be not-a-number.
– chux
Dec 15 '18 at 16:08
2
qsort()
is not specified to be stable.
– chux
Dec 15 '18 at 16:10
2
A 3-way sort is pretty much required for a stable sort. While technically correct, it's not really relevant to a discussion why withqsort()
, "is it really necessary?".
– chux
Dec 15 '18 at 18:11
1
True, The relevancy of requirements of a 3-way sort are a good point for OP to explore - just like the issues of(a == b <-> !(a < b) && !(b < a))
with FP math are good point to explore with sorting.
– chux
Dec 15 '18 at 18:21
It must be noted that (1)
qsort
is not stable and (2) it's not strictly required, but just an optimization - if you only have a "less than" operator, you can deduce the equality by using two comparisons (a == b
<-> !(a < b) && !(b < a)
).– Matteo Italia
Dec 15 '18 at 11:26
It must be noted that (1)
qsort
is not stable and (2) it's not strictly required, but just an optimization - if you only have a "less than" operator, you can deduce the equality by using two comparisons (a == b
<-> !(a < b) && !(b < a)
).– Matteo Italia
Dec 15 '18 at 11:26
1
1
@MatteoItalia
(a == b <-> !(a < b) && !(b < a))
is not certainly true when a,b
are floating point and a value may be not-a-number.– chux
Dec 15 '18 at 16:08
@MatteoItalia
(a == b <-> !(a < b) && !(b < a))
is not certainly true when a,b
are floating point and a value may be not-a-number.– chux
Dec 15 '18 at 16:08
2
2
qsort()
is not specified to be stable.– chux
Dec 15 '18 at 16:10
qsort()
is not specified to be stable.– chux
Dec 15 '18 at 16:10
2
2
A 3-way sort is pretty much required for a stable sort. While technically correct, it's not really relevant to a discussion why with
qsort()
, "is it really necessary?".– chux
Dec 15 '18 at 18:11
A 3-way sort is pretty much required for a stable sort. While technically correct, it's not really relevant to a discussion why with
qsort()
, "is it really necessary?".– chux
Dec 15 '18 at 18:11
1
1
True, The relevancy of requirements of a 3-way sort are a good point for OP to explore - just like the issues of
(a == b <-> !(a < b) && !(b < a))
with FP math are good point to explore with sorting.– chux
Dec 15 '18 at 18:21
True, The relevancy of requirements of a 3-way sort are a good point for OP to explore - just like the issues of
(a == b <-> !(a < b) && !(b < a))
with FP math are good point to explore with sorting.– chux
Dec 15 '18 at 18:21
|
show 3 more comments
qsort
could be written using a boolean compare function instead of a three-way compare but the specification says that it takes a three-way compare function and some (not all) implementations take advantage of the three possible cases. If your compare function doesn't conform to the specification, Undefined Behaviour will result. In this case, Undefined Behaviour might include a failure to sort correctly or a buffer overrun triggered on very rare corner cases, which you might not notice until the space shuttle is returning from orbit. So don't do that.
As to why an implementation might want the three-way comparison, here is one possibility: for inputs with a lot of repeated values, quicksort can be speeded up considerably by using a three-way partition. That can be done with a two-way comparison by doing the comparison twice in opposite directions, but an implementor, knowing that a three-way comparator is required, is likely to test for equality when that's what they want to know.
add a comment |
qsort
could be written using a boolean compare function instead of a three-way compare but the specification says that it takes a three-way compare function and some (not all) implementations take advantage of the three possible cases. If your compare function doesn't conform to the specification, Undefined Behaviour will result. In this case, Undefined Behaviour might include a failure to sort correctly or a buffer overrun triggered on very rare corner cases, which you might not notice until the space shuttle is returning from orbit. So don't do that.
As to why an implementation might want the three-way comparison, here is one possibility: for inputs with a lot of repeated values, quicksort can be speeded up considerably by using a three-way partition. That can be done with a two-way comparison by doing the comparison twice in opposite directions, but an implementor, knowing that a three-way comparator is required, is likely to test for equality when that's what they want to know.
add a comment |
qsort
could be written using a boolean compare function instead of a three-way compare but the specification says that it takes a three-way compare function and some (not all) implementations take advantage of the three possible cases. If your compare function doesn't conform to the specification, Undefined Behaviour will result. In this case, Undefined Behaviour might include a failure to sort correctly or a buffer overrun triggered on very rare corner cases, which you might not notice until the space shuttle is returning from orbit. So don't do that.
As to why an implementation might want the three-way comparison, here is one possibility: for inputs with a lot of repeated values, quicksort can be speeded up considerably by using a three-way partition. That can be done with a two-way comparison by doing the comparison twice in opposite directions, but an implementor, knowing that a three-way comparator is required, is likely to test for equality when that's what they want to know.
qsort
could be written using a boolean compare function instead of a three-way compare but the specification says that it takes a three-way compare function and some (not all) implementations take advantage of the three possible cases. If your compare function doesn't conform to the specification, Undefined Behaviour will result. In this case, Undefined Behaviour might include a failure to sort correctly or a buffer overrun triggered on very rare corner cases, which you might not notice until the space shuttle is returning from orbit. So don't do that.
As to why an implementation might want the three-way comparison, here is one possibility: for inputs with a lot of repeated values, quicksort can be speeded up considerably by using a three-way partition. That can be done with a two-way comparison by doing the comparison twice in opposite directions, but an implementor, knowing that a three-way comparator is required, is likely to test for equality when that's what they want to know.
answered Dec 15 '18 at 15:03
ricirici
153k19135200
153k19135200
add a comment |
add a comment |
If element A ==
element B but the comparator function tells qsort
that B > A
then qsort
will think there may be other elements which should be between A
and B
when that is not the case, and therefore perform unnecessary checks.
add a comment |
If element A ==
element B but the comparator function tells qsort
that B > A
then qsort
will think there may be other elements which should be between A
and B
when that is not the case, and therefore perform unnecessary checks.
add a comment |
If element A ==
element B but the comparator function tells qsort
that B > A
then qsort
will think there may be other elements which should be between A
and B
when that is not the case, and therefore perform unnecessary checks.
If element A ==
element B but the comparator function tells qsort
that B > A
then qsort
will think there may be other elements which should be between A
and B
when that is not the case, and therefore perform unnecessary checks.
answered Dec 15 '18 at 11:21
Weather VaneWeather Vane
25.7k52038
25.7k52038
add a comment |
add a comment |
Technically, you can do with just less-than, because a == b
is equivalent to !(a < b) && !(b < a)
.
1
Independently of Matteo's comment. ;-)
– Yves Daoust
Dec 15 '18 at 11:36
2
That is, assuming full ordering. Seems obvious as we are sorting, but it's important to remember that equivalence does not hold in the general case.
– spectras
Dec 15 '18 at 11:37
2
@yves: if at least one ofa
andb
is NaN, all comparisons returnfalse
. But!false && !false
istrue
.
– rici
Dec 15 '18 at 17:38
3
@yvesDaoust: So was the Boer War, but there it is. (ambiguously signedchar
is way ahead on my list :-)
– rici
Dec 15 '18 at 18:53
2
@YvesDaoust, comparison returning NaN? How would that work? If you didif (a < b)
andb
happened to be NaN, the program would still need to decide if it should run the conditional block or not...
– ilkkachu
Dec 15 '18 at 22:39
|
show 4 more comments
Technically, you can do with just less-than, because a == b
is equivalent to !(a < b) && !(b < a)
.
1
Independently of Matteo's comment. ;-)
– Yves Daoust
Dec 15 '18 at 11:36
2
That is, assuming full ordering. Seems obvious as we are sorting, but it's important to remember that equivalence does not hold in the general case.
– spectras
Dec 15 '18 at 11:37
2
@yves: if at least one ofa
andb
is NaN, all comparisons returnfalse
. But!false && !false
istrue
.
– rici
Dec 15 '18 at 17:38
3
@yvesDaoust: So was the Boer War, but there it is. (ambiguously signedchar
is way ahead on my list :-)
– rici
Dec 15 '18 at 18:53
2
@YvesDaoust, comparison returning NaN? How would that work? If you didif (a < b)
andb
happened to be NaN, the program would still need to decide if it should run the conditional block or not...
– ilkkachu
Dec 15 '18 at 22:39
|
show 4 more comments
Technically, you can do with just less-than, because a == b
is equivalent to !(a < b) && !(b < a)
.
Technically, you can do with just less-than, because a == b
is equivalent to !(a < b) && !(b < a)
.
answered Dec 15 '18 at 11:33
Yves DaoustYves Daoust
37k72559
37k72559
1
Independently of Matteo's comment. ;-)
– Yves Daoust
Dec 15 '18 at 11:36
2
That is, assuming full ordering. Seems obvious as we are sorting, but it's important to remember that equivalence does not hold in the general case.
– spectras
Dec 15 '18 at 11:37
2
@yves: if at least one ofa
andb
is NaN, all comparisons returnfalse
. But!false && !false
istrue
.
– rici
Dec 15 '18 at 17:38
3
@yvesDaoust: So was the Boer War, but there it is. (ambiguously signedchar
is way ahead on my list :-)
– rici
Dec 15 '18 at 18:53
2
@YvesDaoust, comparison returning NaN? How would that work? If you didif (a < b)
andb
happened to be NaN, the program would still need to decide if it should run the conditional block or not...
– ilkkachu
Dec 15 '18 at 22:39
|
show 4 more comments
1
Independently of Matteo's comment. ;-)
– Yves Daoust
Dec 15 '18 at 11:36
2
That is, assuming full ordering. Seems obvious as we are sorting, but it's important to remember that equivalence does not hold in the general case.
– spectras
Dec 15 '18 at 11:37
2
@yves: if at least one ofa
andb
is NaN, all comparisons returnfalse
. But!false && !false
istrue
.
– rici
Dec 15 '18 at 17:38
3
@yvesDaoust: So was the Boer War, but there it is. (ambiguously signedchar
is way ahead on my list :-)
– rici
Dec 15 '18 at 18:53
2
@YvesDaoust, comparison returning NaN? How would that work? If you didif (a < b)
andb
happened to be NaN, the program would still need to decide if it should run the conditional block or not...
– ilkkachu
Dec 15 '18 at 22:39
1
1
Independently of Matteo's comment. ;-)
– Yves Daoust
Dec 15 '18 at 11:36
Independently of Matteo's comment. ;-)
– Yves Daoust
Dec 15 '18 at 11:36
2
2
That is, assuming full ordering. Seems obvious as we are sorting, but it's important to remember that equivalence does not hold in the general case.
– spectras
Dec 15 '18 at 11:37
That is, assuming full ordering. Seems obvious as we are sorting, but it's important to remember that equivalence does not hold in the general case.
– spectras
Dec 15 '18 at 11:37
2
2
@yves: if at least one of
a
and b
is NaN, all comparisons return false
. But !false && !false
is true
.– rici
Dec 15 '18 at 17:38
@yves: if at least one of
a
and b
is NaN, all comparisons return false
. But !false && !false
is true
.– rici
Dec 15 '18 at 17:38
3
3
@yvesDaoust: So was the Boer War, but there it is. (ambiguously signed
char
is way ahead on my list :-)– rici
Dec 15 '18 at 18:53
@yvesDaoust: So was the Boer War, but there it is. (ambiguously signed
char
is way ahead on my list :-)– rici
Dec 15 '18 at 18:53
2
2
@YvesDaoust, comparison returning NaN? How would that work? If you did
if (a < b)
and b
happened to be NaN, the program would still need to decide if it should run the conditional block or not...– ilkkachu
Dec 15 '18 at 22:39
@YvesDaoust, comparison returning NaN? How would that work? If you did
if (a < b)
and b
happened to be NaN, the program would still need to decide if it should run the conditional block or not...– ilkkachu
Dec 15 '18 at 22:39
|
show 4 more comments
If the quicksort inner loop is written equivalent to this:
while(x[i] < pivot) i++; // less-than
while(pivot < x[j]) j--; // less-than
then you can get away with only implementing <
.
In any case, stick to the principle of least astonishment by making it more obvious what the caller is supposed to do -- if your compare function pointer is named compare
and the function shouldn't behave like a usual stdlib qsort
compare delegate, then it's a bad idea.
On the other hand, if your parameter is named something like less_than
or isLessThan
, it should be much more obvious to the caller what is expected from the comparison function:
void sort(
const void * arr,
size_t num_items,
size_t element_size,
bool (*is_less_than)(const void*, const void*)
);
add a comment |
If the quicksort inner loop is written equivalent to this:
while(x[i] < pivot) i++; // less-than
while(pivot < x[j]) j--; // less-than
then you can get away with only implementing <
.
In any case, stick to the principle of least astonishment by making it more obvious what the caller is supposed to do -- if your compare function pointer is named compare
and the function shouldn't behave like a usual stdlib qsort
compare delegate, then it's a bad idea.
On the other hand, if your parameter is named something like less_than
or isLessThan
, it should be much more obvious to the caller what is expected from the comparison function:
void sort(
const void * arr,
size_t num_items,
size_t element_size,
bool (*is_less_than)(const void*, const void*)
);
add a comment |
If the quicksort inner loop is written equivalent to this:
while(x[i] < pivot) i++; // less-than
while(pivot < x[j]) j--; // less-than
then you can get away with only implementing <
.
In any case, stick to the principle of least astonishment by making it more obvious what the caller is supposed to do -- if your compare function pointer is named compare
and the function shouldn't behave like a usual stdlib qsort
compare delegate, then it's a bad idea.
On the other hand, if your parameter is named something like less_than
or isLessThan
, it should be much more obvious to the caller what is expected from the comparison function:
void sort(
const void * arr,
size_t num_items,
size_t element_size,
bool (*is_less_than)(const void*, const void*)
);
If the quicksort inner loop is written equivalent to this:
while(x[i] < pivot) i++; // less-than
while(pivot < x[j]) j--; // less-than
then you can get away with only implementing <
.
In any case, stick to the principle of least astonishment by making it more obvious what the caller is supposed to do -- if your compare function pointer is named compare
and the function shouldn't behave like a usual stdlib qsort
compare delegate, then it's a bad idea.
On the other hand, if your parameter is named something like less_than
or isLessThan
, it should be much more obvious to the caller what is expected from the comparison function:
void sort(
const void * arr,
size_t num_items,
size_t element_size,
bool (*is_less_than)(const void*, const void*)
);
answered Dec 15 '18 at 12:27
GrooGroo
35.3k1484158
35.3k1484158
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53791771%2fwhy-does-the-comparison-function-given-to-qsort-need-to-return-three-different%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
IMO, this is related to the bad habit to perform binary searches as ternary searches, with early termination in case of equality. In most cases, this is counter-productive.
– Yves Daoust
Dec 15 '18 at 11:52