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;
}
CodePudding user response:
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:
Left shift the lower
b
bits to the top (sizeof (d) - (b)
is28
bits in this case). When you left shift the lower bits become 0. With example data the value is0x8000000
.The left followed by right shift clears the top
b
bits, and the right followed by left shift clears the lowerb
bits. With the example data the value is0x02345670
. This equivalent bitwiseAND
of the mask0x0ffffff0
for a 32-bit number. The shift works for any unsigned integer type irregardless of size.Right shift the top
b
bits to the bottom. When you right shift the upperb
bits become zero. With the example data the value is0x00000001
.
#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
CodePudding user response:
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.