Thread: how to pack 8 x 4 bit binary numbers into a long int?

  1. #1
    Registered User
    Join Date
    Nov 2001
    Posts
    7

    how to pack 8 x 4 bit binary numbers into a long int?

    How do I pack 8 4-bit binary numbers into a long int?
    The program is to take an input string of 8 ascii charcaters, (digits 0 to 9 only), convert them to their 4 bit binary equivilants and pack them into a long int.

    eg:
    input string: 13560927

    = 0001 0011 0101 0110 0000 1001 0010 0111.


    thanks...

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    So which bit are you stuck on?
    - reading the input
    - extracting digits
    - storing the bits in a long int?

    All you need is a loop and some use of
    result = result << 4;

  3. #3
    Sayeh
    Guest
    Technically, a 4-bit number is a called 'nyble'. half of a byte.

    working with nybles is easy-- just use masking and shifting. In fact, this is one of the reasons it is easier to work in hex than it is, in decimal, because hex naturally breaks up into nybles.

    0x0 through 0xF = 0-15 decimal = 0000 to 1111 binary.

    In your example,

    0001 0011 0101 0110 0000 1001 0010 0111

    just shift and 'and' (logic operation).

    ---

    unsigned long newlong;
    unsigned long scratch;

    char string[] = '13560927];
    int i;

    newlong = 0L; /* clear to zero */

    for(i=0;i<8;i++)
    {
    scratch = (long)atoi(string[i]);
    scratch <<= ((7-i)*4);

    newlong &= scratch;
    };

    You should end up with a number that is: 0x13560927 hex.

    enjoy.

  4. #4
    Registered User
    Join Date
    Nov 2001
    Posts
    7
    sayeh, what exactly do the lines

    scratch <<= ((7-i)*4);

    newlong &= scratch;

    do in the code you wrote in your reply?

  5. #5
    Registered User goran's Avatar
    Join Date
    Sep 2001
    Posts
    68
    newlong &= scratch;

    we eventually end up with zero in newlong because it has been initialized to zero.

    i m still trying to figure it out sayeh's code..
    I don't wait for the future; it comes soon enough.

  6. #6
    Linguistic Engineer... doubleanti's Avatar
    Join Date
    Aug 2001
    Location
    CA
    Posts
    2,459
    he probably meant |=

    scratch-line shifts the data over the correct number of bits to prep it...

    or-line stores that prepped data into the long int you want...
    hasafraggin shizigishin oppashigger...

  7. #7
    Registered User
    Join Date
    Nov 2001
    Posts
    7

    Talking

    ok here is my modification of his code (but it still doesnt work )

    anyone care to debug it for me?

    #include <stdio.h>

    int main()
    {
    unsigned long newlong;
    unsigned long scratch;

    char string[] = "13560927";
    int i;

    newlong = 0; /* clear to zero */

    for(i=0;i<8;i++)
    {
    scratch = (long)atoi(string[i]);
    scratch <<= ((7-i)*4);

    newlong |= scratch;
    }
    printf("%i", scratch);
    getch();

    return 0;
    }

  8. #8
    Registered User
    Join Date
    Nov 2001
    Posts
    65
    Well atoi accepts a string as its argument and it converts to integer. atol is for longs but your arguments are all chars so your code will cause segmentation faults. Here is the corrected full program.

    #include <stdio.h>
    #include <conio.h>

    void displayBits(unsigned long);

    int main()
    {
    unsigned long newlong;
    unsigned long scratch;

    char string[] = "13560927";
    int i;
    char dummy;


    newlong = 0; /* clear to zero */

    for(i=0;i<8;i++)
    {
    dummy = (string[i] & 0x0f);
    scratch = (unsigned long) dummy;
    scratch <<= ((7-i)*4);

    newlong |= scratch;
    }

    printf("string is: %s\n", string);
    printf("packed in %ld\n", newlong);
    displayBits(newlong);

    getch();

    return 0;
    }

    void displayBits(unsigned long value)
    {
    unsigned long c, displayMask = 1 << 31;

    for (c = 1; c <= 32; c++) {
    putchar(value & displayMask ? '1' : '0');
    value <<= 1;

    if (c%4 == 0)
    putchar(' ');
    }
    putchar('\n');
    }

  9. #9
    Registered User
    Join Date
    Nov 2001
    Posts
    7

    Thumbs up

    thanks for that ozgulker.

    works like a charm

  10. #10
    Sayeh
    Guest
    Thank you for all the help people-- I injured a muscle in my jaw here several weeks ago, and sometimes the pain makes it hard to concentrate.

    Typos result.

    (Oh well, better now)--

    This little line means:

    scratch <<= ((7-i)*4);

    Take 'scratch', shift it left 4 bits for every iteration through the loop, and make it equal to that value. However, since our loop is counting 'left to right' per se, we need to reverse the direction of the count. hence "(7-i)".

    So for example, when examining the first character, we see that it is a '1'. Our loop is at zero.

    '1' in binary = 0000 0000 0000 0000 0000 0000 0000 0001

    newLong == 0x00000000

    So, doing the calculation, we want to shift the '1' left by

    (7-0)*4) = x
    7*4 = x
    28 = x

    shift the '1' left by 28 bits. Like so:

    0001 0000 0000 0000 0000 0000 0000 0000

    newLong == 0x10000000

    ---

    The next number is a '3', and our loop is at '1', so:

    0000 0000 0000 0000 0000 0000 0000 0011

    via the math:

    (7-1)*4) = x
    6*4 = x
    24 = x

    becomes:

    0000 0011 0000 0000 0000 0000 0000 0000


    Then when we OR it with the newLong value:

    newLong == 0x13000000

    ---

    and so on.

    enjoy.

  11. #11
    Registered User
    Join Date
    Nov 2001
    Posts
    7
    thanks for that explanation sayeh, i understand it all now.

  12. #12
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Here's a fun one:
    Code:
    typdef union pack {
        struct {
            int n0:4;
            int n1:4;
            int n2:4;
            int n3:4;
            int n4:4;
            int n5:4;
            int b6:4;
            int n7:4;
        } nyb;
        long l;
    } PACK;
    
    long cram( long l, int spot )
    {
        PACK p;
        switch( spot%8 )
        {
            case 0: p.n0 = l%16; break;
            case 1: p.n1 = l%16; break;
            case 2: p.n2 = l%16; break;
            case 3: p.n3 = l%16; break;
            case 4: p.n4 = l%16; break;
            case 5: p.n5 = l%16; break;
            case 6: p.n6 = l%16; break;
            case 7: p.n7 = l%16; break;
        }
        return p.l;
    }
    See how much fun that was? You could likely use an array of structures of integer x:4; but I haven't tried it, and I know this way will work. If you could use an array of nyb, then you could forgo the case statement with a single line:

    p.n[spot%8] = l%16;

    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how to combine these working parts??
    By transgalactic2 in forum C Programming
    Replies: 0
    Last Post: 02-01-2009, 08:19 AM
  2. Replies: 48
    Last Post: 09-26-2008, 03:45 AM
  3. Replies: 3
    Last Post: 05-13-2007, 08:55 AM
  4. Replies: 1
    Last Post: 10-27-2006, 01:21 PM
  5. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM