-2

Suppose :

No = 77
77 in binary [32 bits] : 0000 0000 0000 0000 0000 0000 0100 1101

I have to swap first and last nibble:

i.e :                    1101 0000 0000 0000 0000 0000 0100 0000

I was doing something like this:

no << 32 | no >> 32

Then in a loop anding it with 1 and printing. But it does not work out.

#include<stdio.h>

int main()
{

    int decimalNumber;
    printf("Enter your decimal number: ");
    scanf("%d", &decimalNumber);
    int i, j;
    
    /* Binary conversion */
    for(i=31;i>=0;i--)
    {

        printf("%d", (decimalNumber >> i) & 1);
    }
    printf("\n");
    printf("After nibble swapping: \n");
    /* Nibble swapping */
    decimalNumber = (decimalNumber>>28) | (decimalNumber<<28);
    for(i=31;i>=0;i--)
    {
        printf("%d",((decimalNumber>>i)&1 ? 1 : 0));
    }
    printf("\n");
    return 0;
}
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
Manvi Koul
  • 15
  • 4
  • Edit your question and include some code (as text). – Allan Wind Jan 25 '23 at 07:43
  • Shifting by 32 is too far. – tkausl Jan 25 '23 at 07:43
  • _"Then in a loop anding it with 1 and printing. But it does not work out."_: it would be more helpful if you showed your code instead of describing it. Read this: [mcve] – Jabberwocky Jan 25 '23 at 08:10
  • I have posted the code. – Manvi Koul Jan 25 '23 at 09:13
  • This is the output produced by the code Output: Enter your decimal number: 77 00000000000000000000000001001101 After nibble swapping: 11010000000000000000000000000000 But the expected output after nibble swapping is : 11010000000000000000000001000000 – Manvi Koul Jan 25 '23 at 09:13
  • Can anyone help me out with this as i am new to this concept and stuck on the issue – Manvi Koul Jan 25 '23 at 09:14
  • Don't use `int`, it's size is platform specific, and your problem only really make sense for unsigned values. – Allan Wind Jan 25 '23 at 11:34
  • `decimalNumber = (decimalNumber>>28) | (decimalNumber<<28);` swap the lower an upper bits but you lose the middle 24 bits. – Allan Wind Jan 25 '23 at 11:40
  • `decimalNumber & 0x0ffffff0` is the middle bits, or you can use the shift pattern in my answer below `decimalNumber << 4 >> 4 >> 4 << 4`. Also instead of duplicating the code to print a binary number write a function `void print_bits(unsigned int v) { for(int i=31;i>=0; i--) printf("%d", (v >> i) & 1); }` – Allan Wind Jan 25 '23 at 11:47

2 Answers2

2

Given an unsigned integer d and b number of bits where b <= CHAR_BIT * sizeof(d) / 2 you obtain the result by bitwise OR of these components:

  1. Left shift the lower b bits to the top (sizeof (d) - (b) is 28 bits in this case). When you left shift the lower bits become 0. With example data the value is 0x8000000.

  2. The left followed by right shift clears the top b bits, and the right followed by left shift clears the lower b bits. With the example data the value is 0x02345670. This equivalent bitwise AND of the mask 0x0ffffff0 for a 32-bit number. The shift works for any unsigned integer type irregardless of size.

  3. Right shift the top b bits to the bottom. When you right shift the upper b bits become zero. With the example data the value is 0x00000001.

#include <limits.h>
#include <stdio.h>
#include <stdint.h>

#define SWAP_BITS(d, b) \
    /* 1 */ (d) << CHAR_BIT * sizeof (d) - (b) |\
    /* 2 */ (d) << (b) >> (b) >> (b) << (b) |\
    /* 3 */ (d) >> CHAR_BIT * sizeof (d) - (b)

int main() {
    uint32_t d = 0x12345678;
    printf("%x\n%x\n", d, SWAP_BITS(d, 4));
}

and the outcome is:

82345671
Allan Wind
  • 23,068
  • 5
  • 28
  • 38
0

swap first and last nibbles in given integer (32 bits)

OP's decimalNumber = (decimalNumber>>28) | (decimalNumber<<28); fails as the | or's the data, not replace it. Also shifting by 28 shifts the middle bits, which need to remain in place.


  • Use unsigned types to not shift into or out of the sign bit.

  • For a fixed sized tasks, consider using fixed sized types from #include <stdint.h>.

  • Print data with %X to better see what is happening.

    uint32_t uvalue = decimalNumber;
    printf("Before %lu\n", (unsigned long) uvalue);   // In decimal
    printf("Before 0x%lX\n", (unsigned long) uvalue); // In hexadecimal

    // Get first (most significant) and last (least significant) nibble.
    uint32_t first_nibble = uvalue >> (32-4);
    uint32_t last_nibble = uvalue & 0xF;

    // zero out the first and last nibble.
    uvalue &= 0x0FFFFFF0; 
    // Now "or" in the replacement nibbles.
    uvalue |= first_nibble;
    uvalue |= last_nibble << (32-4);

    printf("After 0x%lX\n", (unsigned long) uvalue);
    printf("After %lu\n", (unsigned long) uvalue);

For those who like one-liners

printf("After %lu\n", (unsigned long) (
    (((uint32_t) decimalNumber) & 0xF) << 28) |
    ((uint32_t) decimalNumber) & 0x0FFFFFF0) |
    ((uint32_t) decimalNumber) >> 28) |
    )); 

Some would consider the first nibble as the least significant nibble. Whatever is first or last makes little difference here as they are swapped.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256