Why does the comparison function given to qsort() need to return three different values?












7















I have read that the comparison function required by qsort() needs to have 3 outcomes:




  • a negative result if val1 < val2


  • 0 if val1 == 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?










share|improve this question




















  • 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


















7















I have read that the comparison function required by qsort() needs to have 3 outcomes:




  • a negative result if val1 < val2


  • 0 if val1 == 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?










share|improve this question




















  • 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
















7












7








7








I have read that the comparison function required by qsort() needs to have 3 outcomes:




  • a negative result if val1 < val2


  • 0 if val1 == 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?










share|improve this question
















I have read that the comparison function required by qsort() needs to have 3 outcomes:




  • a negative result if val1 < val2


  • 0 if val1 == 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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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
















  • 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














5 Answers
5






active

oldest

votes


















1














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.






share|improve this answer


























  • 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 when a,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 with qsort(), "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



















4














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.






share|improve this answer































    3














    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.






    share|improve this answer































      2














      Technically, you can do with just less-than, because a == b is equivalent to !(a < b) && !(b < a).






      share|improve this answer



















      • 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 of a and b is NaN, all comparisons return false. But !false && !false is true.

        – rici
        Dec 15 '18 at 17:38






      • 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






      • 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



















      1














      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*)
      );





      share|improve this answer























        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
        });


        }
        });














        draft saved

        draft discarded


















        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









        1














        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.






        share|improve this answer


























        • 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 when a,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 with qsort(), "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
















        1














        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.






        share|improve this answer


























        • 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 when a,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 with qsort(), "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














        1












        1








        1







        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.






        share|improve this answer















        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.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        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 when a,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 with qsort(), "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






        • 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






        • 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 with qsort(), "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













        4














        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.






        share|improve this answer




























          4














          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.






          share|improve this answer


























            4












            4








            4







            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.






            share|improve this answer













            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.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Dec 15 '18 at 15:03









            ricirici

            153k19135200




            153k19135200























                3














                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.






                share|improve this answer




























                  3














                  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.






                  share|improve this answer


























                    3












                    3








                    3







                    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.






                    share|improve this answer













                    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.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Dec 15 '18 at 11:21









                    Weather VaneWeather Vane

                    25.7k52038




                    25.7k52038























                        2














                        Technically, you can do with just less-than, because a == b is equivalent to !(a < b) && !(b < a).






                        share|improve this answer



















                        • 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 of a and b is NaN, all comparisons return false. But !false && !false is true.

                          – rici
                          Dec 15 '18 at 17:38






                        • 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






                        • 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
















                        2














                        Technically, you can do with just less-than, because a == b is equivalent to !(a < b) && !(b < a).






                        share|improve this answer



















                        • 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 of a and b is NaN, all comparisons return false. But !false && !false is true.

                          – rici
                          Dec 15 '18 at 17:38






                        • 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






                        • 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














                        2












                        2








                        2







                        Technically, you can do with just less-than, because a == b is equivalent to !(a < b) && !(b < a).






                        share|improve this answer













                        Technically, you can do with just less-than, because a == b is equivalent to !(a < b) && !(b < a).







                        share|improve this answer












                        share|improve this answer



                        share|improve this answer










                        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 of a and b is NaN, all comparisons return false. But !false && !false is true.

                          – rici
                          Dec 15 '18 at 17:38






                        • 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






                        • 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














                        • 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 of a and b is NaN, all comparisons return false. But !false && !false is true.

                          – rici
                          Dec 15 '18 at 17:38






                        • 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






                        • 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








                        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











                        1














                        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*)
                        );





                        share|improve this answer




























                          1














                          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*)
                          );





                          share|improve this answer


























                            1












                            1








                            1







                            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*)
                            );





                            share|improve this answer













                            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*)
                            );






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Dec 15 '18 at 12:27









                            GrooGroo

                            35.3k1484158




                            35.3k1484158






























                                draft saved

                                draft discarded




















































                                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.




                                draft saved


                                draft discarded














                                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





















































                                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







                                Popular posts from this blog

                                Bressuire

                                Cabo Verde

                                Gyllenstierna