Problem when qsorting an array of floats

This is a discussion on Problem when qsorting an array of floats within the C Programming forums, part of the General Programming Boards category; Hi, I am trying to qsort an array of floats and for some reason I am not getting the proper ...

  1. #1
    Registered User
    Join Date
    Feb 2009
    Posts
    26

    Problem when qsorting an array of floats

    Hi,

    I am trying to qsort an array of floats and for some reason I am not getting the proper results. I am posting my code here. Could any of you take a look and tell me what I am missing.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int compare(const void*a, const void*b)
    {
    
     int a1 =  ( *(float*) a);
     int a2 =  ( *(float*) b);
     
      return a1 -a2;
    }
    
    
    int main()
    {
    
      float array[] = { 1605748992, 2242276608, 6265311232, 8249718272, 1181892352, 2202173184, 411911232, 6999099904, 11551354880, 5034336768,2997344512,636791104,1221603328,2306947328,7531588096,8709864448,7865203712,1004122048,2171712000,4130571776,4451974656 };
    
      int i,j, lib_no =21;
    
      for(i=0; i<lib_no; i++)
      {
    
        printf("%f\n",array[i]);
    
      }
    
      printf("\n\n\n\n");
    
      qsort(&array[0], lib_no, sizeof(float), compare);
    
    
      for(i=0; i<lib_no; i++)
      {
    
        printf("%f\n",array[i] );
    
      }
    
     return 0;
    }
    When I run this, I am getting an array which is ordered differently from the original array. But not properly sorted.

    I think that the problem is something in the the way I am typecasting the void pointers inside the compare function. But not sure what..I was earlier doing it like this..

    Code:
    int compare(const void*a, const void*b)
    {
    
     return (int) ( *(float*)a - *(float*)b) );
    }
    and that gave me an output with a different order. But again not properly sorted. Does anyone have any suggestions on what I should try? What am I doing wrong?

    Thanks,

    Avinash

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
     int a1 =  ( *(float*) a);
     int a2 =  ( *(float*) b);
    See anything wrong there?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,310
    I tried compiling your code, and my compiler alerted me that the integer constants that you used are too long to fit into a long on my system, and that may well be the case for you as well. One obvious solution would be to use float constants instead, e.g., by appending a .0f to each of your currently integer constants.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Yes, I noticed what Laserlight says too. You also can't do what you did with subtracting one integer from another and expect the result to be sensible if your values are that large. You need to actually compare floating point numbers and then return 0, -1 or 1 depending on which order the numbers were.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Registered User
    Join Date
    Feb 2009
    Posts
    26
    @Matsp: Sorry bout that.. My bad. But fixing that typecast to
    Code:
     int a1 = (int) (* (float *) a)
    doesn't mean to make much difference. I still get the same output. Btw, if I assign a float to an int, isn't it usually automatically converted?

    @Laserlight: You maybe right. Do u mean i should change my code to something like
    Code:
    int compare(const void*a, const void*b)
    {
    
     float a1 =  ( *(float*) a);
     float a2 =  ( *(float*) b);
     
      return (int) a1 -a2;
    }
    .

    I tried that and i still get a bad o/p..

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,310
    Quote Originally Posted by avi2886
    Do u mean i should change my code to something like
    Personally, I would write:
    Code:
    int compare(const void *a, const void *b)
    {
        const float x = *(float*)a;
        const float y = *(float*)b;
        if (x < y)
        {
            return -1;
        }
        else if (x > y)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
    or if you prefer compact code:
    Code:
    int compare(const void *a, const void *b)
    {
        const float x = *(float*)a;
        const float y = *(float*)b;
        return (x < y) ? -1 : (x > y);
    }
    Last edited by laserlight; 04-30-2009 at 01:03 PM.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Feb 2009
    Posts
    26
    Oh.. Tat works!. Thanks a ton for the help.. Not being able to figure that out was driving me nuts.

    So.. the problem was that when I just return the difference between 2 numbers, sometimes the return value might be too large that it might overflow int or something. So an very large difference might actually become a negative value. Thus messing up the order. Is that correct?

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,310
    Quote Originally Posted by avi2886
    So.. the problem was that when I just return the difference between 2 numbers, sometimes the return value might be too large that it might overflow int or something. So an very large difference might actually become a negative value. Thus messing up the order. Is that correct?
    Well, one problem was that just initialising ints with floats could result in loss of information, e.g., 0.5 and 0.7 would both become 0. You identified the next problem. That said, this problem in subtraction (or addition, etc) is more general, the result of the overflow may be implementation defined.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Feb 2009
    Posts
    26
    Yes.. Got it now. Thanks for the explanation. Cheers..

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Array problem
    By TomBoyRacer in forum C++ Programming
    Replies: 3
    Last Post: 04-08-2007, 11:35 AM
  2. Replies: 6
    Last Post: 02-15-2005, 10:20 PM
  3. Problem Putting INTs Into a CHAR Array
    By cram in forum C++ Programming
    Replies: 13
    Last Post: 10-13-2004, 07:53 AM
  4. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM
  5. Merge sort please
    By vasanth in forum C Programming
    Replies: 2
    Last Post: 11-09-2003, 11:09 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21