I'm to stupid right now to solve this problem...
I get a BCD number (every digit is an own 4Bit representation)
For example, what I want:
Input: 202 (hex) == 514 (dec)
Output: BCD 0x415
Input: 0x202
Bit-representation: 0010 0000 0010 = 514
What have I tried:
unsigned int uiValue = 0x202;
unsigned int uiResult = 0;
unsigned int uiMultiplier = 1;
unsigned int uiDigit = 0;
// get the dec bcd value
while ( uiValue > 0 )
{
uiDigit= uiValue & 0x0F;
uiValue >>= 4;
uiResult += uiMultiplier * uiDigit;
uiMultiplier *= 10;
}
But I know that's very wrong this would be 202 in Bit representation and then split into 5 nibbles and then represented as decimal number again
I can solve the problem on paper but I just cant get it in a simple C-Code
You got it the wrong way round. Your code is converting from BCD to binary, just as your question's (original) title says. But the input and output values you provided are correct only if you convert from binary to BCD. In that case, try:
#include <stdio.h>
int main(void) {
int binaryInput = 0x202;
int bcdResult = 0;
int shift = 0;
printf("Binary: 0x%x (dec: %d)\n", binaryInput , binaryInput );
while (binaryInput > 0) {
bcdResult |= (binaryInput % 10) << (shift++ << 2);
binaryInput /= 10;
}
printf("BCD: 0x%x (dec: %d)\n", bcdResult , bcdResult );
return 0;
}
Proof: http://ideone.com/R0reQh
Try the following.
unsigned long toPackedBcd (unsigned int val)
{
unsigned long bcdresult = 0; char i;
for (i = 0; val; i++)
{
((char*)&bcdresult)[i / 2] |= i & 1 ? (val % 10) << 4 : (val % 10) & 0xf;
val /= 10;
}
return bcdresult;
}
Also one may try the following variant (although maybe little inefficient)
/*
Copyright (c) 2016 enthusiasticgeek<enthusiasticgeek#gmail.com> Binary to Packed BCD
This code may be used (including commercial products) without warranties of any kind (use at your own risk)
as long as this copyright notice is retained.
Author, under no circumstances, shall not be responsible for any code crashes or bugs.
Exception to copyright code: 'reverse string function' which is taken from http://stackoverflow.com/questions/19853014/reversing-a-string-in-place-in-c-pointers#19853059
Double Dabble Algorithm for unsigned int explanation
255(binary) - base 10 -> 597(packed BCD) - base 16
H| T| U| (Keep shifting left)
11111111
1 1111111
11 111111
111 11111
1010 11111 <-----added 3 in unit's place (7+3 = 10)
1 0101 1111
1 1000 1111 <-----added 3 in unit's place (5+3 = 8)
11 0001 111
110 0011 11
1001 0011 11 <-----added 3 in ten's place (6+3 = 9)
1 0010 0111 1
1 0010 1010 1 <-----added 3 in unit's place (7+3 = 10)
10 0101 0101 -> binary 597 but bcd 255
^ ^ ^
| | |
2 5 5
*/
#include <stdio.h>
#include <string.h>
//Function Prototypes
unsigned int binaryToPackedBCD (unsigned int binary);
char * printPackedBCD(unsigned int bcd, char * bcd_string);
// For the following function see http://stackoverflow.com/questions/19853014/reversing-a-string-in-place-in-c-pointers#19853059
void reverse(char *str);
//Function Definitions
unsigned int binaryToPackedBCD (unsigned int binary) {
const unsigned int TOTAL_BITS = 32;
/*Place holder for bcd*/
unsigned int bcd = 0;
/*counters*/
unsigned int i,j = 0;
for (i=0; i<TOTAL_BITS; i++) {
/*
Identify the bit to append to LSB of 8 byte or 32 bit word -
First bitwise AND mask with 1.
Then shift to appropriate (nth shift) place.
Then shift the result back to the lsb position.
*/
unsigned int binary_bit_to_lsb = (1<<(TOTAL_BITS-1-i)&binary)>>(TOTAL_BITS-1-i);
/*shift by 1 place and append bit to lsb*/
bcd = ( bcd<<1 ) | binary_bit_to_lsb;
/*printf("=> %u\n",bcd);*/
/*Don't add 3 for last bit shift i.e. in this case 32nd bit*/
if( i >= TOTAL_BITS-1) {
break;
}
/*else continue*/
/* Now, check every nibble from LSB to MSB and if greater than or equal 5 - add 3 if so */
for (j=0; j<TOTAL_BITS; j+=4) {
unsigned int temp = (bcd & (0xf<<j))>>j;
if(temp >= 0x5) {
/*printf("[%u,%u], %u, bcd = %u\n",i,j, temp, bcd);*/
/*Now, add 3 at the appropriate nibble*/
bcd = bcd + (3<<j);
// printf("Now bcd = %u\n", bcd);
}
}
}
/*printf("The number is %u\n",bcd);*/
return bcd;
}
char * printPackedBCD(unsigned int bcd, char * bcd_string) {
const unsigned int TOTAL_BITS = 32;
printf("[LSB] =>\n");
/* Now, check every nibble from LSB to MSB and convert to char* */
for (unsigned int j=0; j<TOTAL_BITS; j+=4) {
//for (unsigned int j=TOTAL_BITS-1; j>=4; j-=4) {
unsigned int temp = (bcd & (0xf<<j))>>j;
if(temp==0){
bcd_string[j/4] = '0';
} else if(temp==1){
bcd_string[j/4] = '1';
} else if(temp==2){
bcd_string[j/4] = '2';
} else if(temp==3){
bcd_string[j/4] = '3';
} else if(temp==4){
bcd_string[j/4] = '4';
} else if(temp==5){
bcd_string[j/4] = '5';
} else if(temp==6){
bcd_string[j/4] = '6';
} else if(temp==7){
bcd_string[j/4] = '7';
} else if(temp==8){
bcd_string[j/4] = '8';
} else if(temp==9){
bcd_string[j/4] = '9';
} else {
bcd_string[j/4] = 'X';
}
printf ("[%u - nibble] => %c\n", j/4, bcd_string[j/4]);
}
printf("<= [MSB]\n");
reverse(bcd_string);
return bcd_string;
}
// For the following function see http://stackoverflow.com/questions/19853014/reversing-a-string-in-place-in-c-pointers#19853059
void reverse(char *str)
{
if (str != 0 && *str != '\0') // Non-null pointer; non-empty string
{
char *end = str + strlen(str) - 1;
while (str < end)
{
char tmp = *str;
*str++ = *end;
*end-- = tmp;
}
}
}
int main(int argc, char * argv[])
{
unsigned int number = 255;
unsigned int bcd = binaryToPackedBCD(number);
char bcd_string[8];
printPackedBCD(bcd, bcd_string);
printf("Binary (Base 10) = %u => Packed BCD (Base 16) = %u\n OR \nPacked BCD String = %s\n", number, bcd, bcd_string);
return 0;
}
The real problem here is confusion of bases and units
The 202 should be HEX which equates to 514 decimal... and therefore the BCD calcs are correct
Binary code decimal will convert the decimal (514) into three nibble sized fields:
- 5 = 0101
- 1 = 0001
- 4 = 0100
The bigger problem was that you have the title the wrong way around, and you are converting Uint to BCD, whereas the title asked for BCD to Unint
My 2 cents, I needed similar for a RTC chip which used BCD to encode the time and date info. Came up with the following macros that worked fine for the requirement:
#define MACRO_BCD_TO_HEX(x) ((BYTE) ((((x >> 4) & 0x0F) * 10) + (x & 0x0F)))
#define MACRO_HEX_TO_BCD(x) ((BYTE) (((x / 10 ) << 4) | ((x % 10))))
A naive but simple solution:
char buffer[16];
sprintf(buffer, "%d", var);
sscanf(buffer, "%x", &var);
This is the solution that I developed and works great for embedded systems, like Microchip PIC microcontrollers:
#include <stdio.h>
void main(){
unsigned int output = 0;
unsigned int input;
signed char a;
//enter any number from 0 to 9999 here:
input = 1265;
for(a = 13; a >= 0; a--){
if((output & 0xF) >= 5)
output += 3;
if(((output & 0xF0) >> 4) >= 5)
output += (3 << 4);
if(((output & 0xF00) >> 8) >= 5)
output += (3 << 8);
output = (output << 1) | ((input >> a) & 1);
}
printf("Input decimal or binary: %d\nOutput BCD: %X\nOutput decimal: %u\n", input, output, output);
}
This is my version for a n byte conversion:
//----------------------------------------------
// This function converts n bytes Binary (up to 8, but can be any size)
// value to n bytes BCD value or more.
//----------------------------------------------
void bin2bcdn(void * val, unsigned int8 cnt)
{
unsigned int8 sz, y, buff[20]; // buff = malloc((cnt+1)*2);
if(cnt > 8) sz = 64; // 8x8
else sz = cnt * 8 ; // Size in bits of the data we shift
memset(&buff , 0, sizeof(buff)); // Clears buffer
memcpy(&buff, val, cnt); // Copy the data to buffer
while(sz && !(buff[cnt-1] & 0x80)) // Do not waste time with null bytes,
{ // so search for first significative bit
rotate_left(&buff, sizeof(buff)); // Rotate until we find some data
sz--; // Done this one
}
while(sz--) // Anyting left?
{
for( y = 0; y < cnt+2; y++) // Here we fix the nibbles
{
if(((buff[cnt+y] + 0x03) & 0x08) != 0) buff[cnt+y] += 0x03;
if(((buff[cnt+y] + 0x30) & 0x80) != 0) buff[cnt+y] += 0x30;
}
rotate_left(&buff, sizeof(buff)); // Rotate the stuff
}
memcpy(val, &buff[cnt], cnt); // Copy the buffer to the data
// free(buff); //in case used malloc
} // :D Done
long bin2BCD(long binary) { // double dabble: 8 decimal digits in 32 bits BCD
if (!binary) return 0;
long bit = 0x4000000; // 99999999 max binary
while (!(binary & bit)) bit >>= 1; // skip to MSB
long bcd = 0;
long carry = 0;
while (1) {
bcd <<= 1;
bcd += carry; // carry 6s to next BCD digits (10 + 6 = 0x10 = LSB of next BCD digit)
if (bit & binary) bcd |= 1;
if (!(bit >>= 1)) return bcd;
carry = ((bcd + 0x33333333) & 0x88888888) >> 1; // carrys: 8s -> 4s
carry += carry >> 1; // carrys 6s
}
}
Simple solution
#include <stdio.h>
int main(void) {
int binaryInput = 514 ; //0x202
int bcdResult = 0;
int digit = 0;
int i=1;
printf("Binary: 0x%x (dec: %d)\n", binaryInput , binaryInput );
while (binaryInput > 0) {
digit = binaryInput %10; //pick digit
bcdResult = bcdResult+digit*i;
i=16*i;
binaryInput = binaryInput/ 10;
}
printf("BCD: 0x%x (dec: %d)\n", bcdResult , bcdResult );
return 0;
}
Binary: 0x202 (dec: 514)
BCD: 0x514 (dec: 1300)
You can also try the following:
In every iteration the remainder ( represented as a nibble ) is positioned in its corresponding place.
uint32_t bcd_converter(int num)
{
uint32_t temp=0;
int i=0;
while(num>0){
temp|=((num%10)<<i);
i+=4;
num/=10;
}
return temp;
}
Related
I'm trying to make a binary representation of an integer using binary() function and then use reverse() function to get bit reversal as can be seen below:
#include <stdio.h>
unsigned char reverse(unsigned char b) {
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b;
}
int binary(int n)
{
int b;
if (n == 0)
{
return 0;
}
else
{
b = (n % 2) + 10 * binary(n / 2);
unsigned char i = (unsigned char)b;
return reverse(i);
}
}
int main()
{
int n;
printf("Enter a decimal number: ");
scanf("%d", &n);
printf("The binary equivalent of %d is %d\n", n, binary(n));
return 0;
}
The issue I'm having is that I expect binary() to produce a binary number (for example, a binary representation fo 18 would be 10010), and then reverse() function to take this number and produce a reversed binary representation starting with the least significant bit (LSB) which should be 01001 in this case. However, when I try to run it, I get returned 0.
I'm new to C and I'm thinking maybe the issue is in the unsigned char datatype, but when, why if I convert b into unsigned char it still doesn't work?
When reversing the bits, all you have to do is check the LSB. Add that value to an output variable. Then shift the output variable by one to the left and shift the original number by one to the right. In the mathematical example below, I do a first 0 shift so it become easier on the eye with the formatting.
In your example of 10010:
Round 1: output = (00000 << 1) + (10010 & 1) = 00000
N = 10010 >> 1 = 01001
Round 2: output = (00000 << 1) + (01001 & 1) = 00001
N = 01001 >> 1 = 00100
Round 3: output = (00001 << 1) + (00100 & 1) = 00010
N = 00100 >> 1 = 00010
Round 4: output = (00010 << 1) + (0010 & 1) = 00100
N = 00010 >> 1 = 00001
Round 5: output = (00100 << 1) + (00001 & 1) = 01001
N = 00001 >> 1 = 00000
Example:
#include <stdio.h>
int binary(int n)
{
int output = 0;
if ( n == 0 ) return 0;
// Save one left shift
output += n & 1;
n = n >> 1;
while( n != 0 ){
output = output << 1;
output += n & 1;
n = n >> 1;
printf("%d\n", output);
}
return output;
}
void printBin(int n){
char bin[33] = {0};
for (int i = 31; i > -1; i-- ){
bin[i] = (char)((n & 1) ^ 48);
n = n >> 1;
}
puts(bin);
}
int main()
{
int n; int rb;
printf("Enter a decimal number: ");
scanf("%d", &n);
rb = binary(n);
printf("The binary equivalent of %d is %d\n", n, rb);
printf("%11d:", n);
printBin(n);
printf("%11d:", rb);
printBin(rb);
return 0;
}
I'm not able to get the right output when I do the following code. look at the comments for what I'm trying to print.
I did the code based on what I've been learning so far, but I'm still not getting the right output.
So any suggestions? What have I done, so I'm able to fix the problem.
When I print(A), I'm not getting 0100 0001, but it prints 49d or 49 sometimes
#include <stdio.h>
unsigned char getBit(unsigned char c, int n)
{
return ((c & (1 << n)) >> n);
}
unsigned char setBit(unsigned char c, int n)
{
c = c | (1 << n);
return c;
}
unsigned char clearBit(unsigned char c, int n)
{
c = c & (~(1 << n));
return c;
}
void printBits(unsigned char c)
{
printf("The bit of the character you inputed is %x \n", c);
}
int main(void)
{
unsigned char a = 'A';
printBits(a);
putchar('\n');
a = setBit(a, 2);
a = setBit(a, 3);
printBits(a); //should print 0100 0001, but it prints 49
putchar('\n');
a = clearBit(a, 2);
printBits(a);
putchar('\n');
}
Your current solution prints the value of c as a hexadecimal number using printf(). Since there is no printf format specifier to print a number in binary representation, we'll have to write our own solution.
#include <limits.h>
#include <stdio.h>
void printBits(byte c)
{
for (unsigned i = CHAR_BIT; i;) { // count from the with of a char
// in bits down to 1
putchar(c & 1 << --i // test the i-th bit (1-based)
? '1' // if true (different form 0) evaluates to '1'
: '0' // else evaluates to '0'
);
if (CHAR_BIT == 8 && i % 4 == 0) // if we use 8-bit-bytes and just
// finished printing the higher nibble
putchar(' '); // insert a seperator between the nibbles
}
}
... ftw!
No-nonsense version:
void printBits(byte c)
{
for (unsigned i = CHAR_BIT; i;) {
putchar(c & 1 << --i ? '1' : '0');
if (CHAR_BIT == 8 && !(i % 4))
putchar(' ');
}
}
`
unsigned char a = 'A';
printBits(a); // should print 0100 0001
putchar('\n');
a = setBit(a, 2);
a = setBit(a, 3);
printBits(a); // should print 0100 1101
putchar('\n');
a = clearBit(a, 2);
printBits(a); // should print 0100 1001
putchar('\n'
I'm trying to implement a FAT12 file system in which there's a FAT table data structure which is an unsigned char array. I need to write a function which given an array index would write a value to the next 12 bits (because it's FAT12) which is quite tricky because part of the value needs to go to one byte and the other part needs to go the half of the second byte.
This is the get value function I came up with:
//FAT is the unsigned char array
int GetFatEntry(int FATindex, unsigned char * FAT) {
unsigned int FATEntryCode; // The return value
// Calculate the offset of the WORD to get
int FatOffset = ((FATindex * 3) / 2);
if (FATindex % 2 == 1){ // If the index is odd
FATEntryCode = ((unsigned char)(&FAT[FatOffset])[0] + (((unsigned char)(&FAT[FatOffset])[1]) << 8));
FATEntryCode >>= 4; // Extract the high-order 12 bits
}
else{ // If the index is even
FATEntryCode = ((unsigned char)(&FAT[FatOffset])[0] + (((unsigned char)(&FAT[FatOffset])[1]) << 8));
FATEntryCode &= 0x0fff; // Extract the low-order 12 bits
}
return FATEntryCode;
}
I'm struggling to come up with the function which would set a value given a FATindex. I would appreciate any suggestions.
This seems to work. The data that should be written should be in the first 12 bits of data
void WriteFatEntry(int FATindex, unsigned char * FAT, unsigned char data[2]) {
// Calculate the offset of the WORD to get
int FatOffset = ((FATindex * 3) / 2);
unsigned char d;
if (FATindex % 2 != 0){ // If the index is odd
// Copy from data to d and e, and shift everything so that second half of
// e contains first half of data[1], and first half of e contains second
// half of data[0], while second half of d contains first half of data[0].
// First half of d contains a copy of first four bits in FAT[FatOffset]
// so that nothing changes when it gets written
unsigned char e=data[1];
e>>=4;
d=data[0];
e|=(d<<4) & 0b11110000;
d>>=4;
d |= FAT[FatOffset] & 0b11110000;
FAT[FatOffset]=d;
FAT[FatOffset+1] = e;
}
else{ // If the index is even
d = data[1] & 0b11110000;
d |= FAT[FatOffset+1] & 0b00001111;
FAT[FatOffset] = data[0];
FAT[FatOffset+1] = d;
}
}
#include <stdio.h>
#if 1 /* assuming MSB first */
#define MSB (idx)
#define LSB (idx+1)
#else /* assuming LSB first */
#define MSB (idx+1)
#define LSB (idx)
#endif
unsigned fat_getval(unsigned char * tab, unsigned num)
{
unsigned idx;
unsigned val;
idx = num + num/2;
val = (tab[MSB] <<8 ) + (tab[idx+1] ) ;
if (num %2 ==0) val >>= 4;
return val & 0xfff;
}
void fat_putval(unsigned char * tab, unsigned slot, unsigned val)
{
unsigned idx;
idx = slot + slot/2;
if (slot %2 ==0) { /* xyz_ */
val <<= 4;
val |= tab[LSB] & 0xf;
}
else { /* _xyz */
val |= (tab[MSB] & 0xf0) << 8;
}
tab[MSB] = val >>8;
tab[LSB] = val &0xff;
}
#undef MSB
#undef LSB
unsigned char fattable[] = "\x01\x23\x45\x67\x89\xab"; // 12 nibbles
int main(void)
{
unsigned idx, ret;
for (idx = 0; idx < 6; idx++) { // 6 bytes -> 12 nibbles */
printf(" %02x", fattable[idx] );
}
printf("\n");
printf("Put(0,0xabc):\n");
fat_putval(fattable, 0, 0xabc);
for (idx = 0; idx < 6; idx++) {
printf(" %02x", fattable[idx] );
}
printf("\n");
printf("Put(3,0xdef):\n");
fat_putval(fattable, 3, 0xdef);
for (idx = 0; idx < 6; idx++) {
printf(" %02x", fattable[idx] );
}
printf("\n");
printf("Get(0 to 4):\n");
for (idx = 0; idx < 4; idx++) { // 12 / 3 ~> 4 * 12bit entries
ret = fat_getval( fattable, idx);
printf("%u := %x\n", idx, ret );
}
printf("\n");
return 0;
}
Logic to set a bits of given number (as show in example below) from first occurance of 1 next should must be 1 and then alternative 0 and 1 should continue till all bits field is filled up? example if num =10 then its binary is 0000 0000 0000 0000 0000 0000 0000 1010
out put should be 0000 0000 0000 0000 0000 0000 0000 1101
similar if it is 16 10000 then 0/p should be 11010 and if 15 ie 1111 then output 11010 when we get first bits as 1 in give number then next bits should be 1 and the alternative 0 and 1?my logic is below please help to fix it
int main()
{
int i,onetime=1,flag=1;
scanf("%d",&num);
for(i=31;i>=0;i++)
{
if(num & 1<<i)
break; // this will give first set bits of num ie 1
}
--i; // move to next adjacent bit and this should also be 1
for(;i>0;)
{
if(onetime=1) // here forcely making 1
{
num=num|1<<i;
onetime=0;
}
if(flag==1) // set to 0
{
num=num&~(1<<i)
flag=0;
}
if(flag==0) //set to 1
{
num=num|(1<<i);
flag =1-flag; //will keep on switch 0 and 1
}
}
}
While the logic behind doing what you want to do it fairly trivial, the implementation isn't. Ignoring the need to output a binary representation for the moment, the logic can be broken down to:
1.) finding the most significant bit (msb)
2.) toggling each bit beginning at (msb - 1) to 0 (subtracting 'x' from msb)
3.) setting each bit if (x % 2) == 0, clearing otherwise
The implementation isn't difficult, it is just rather involved (note: this is for 32-bit values only):
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <limits.h> /* for CHAR_BIT */
inline int getmsb (uint32_t x);
char *fmtbinstr_32 (uint32_t x, const size_t szgrp, char *sep);
/* set or clear bit n */
inline void bit_set (uint32_t *bf, int n) { *bf |= (1 << n); }
inline void bit_clear (uint32_t *bf, int n) { *bf &= ~(1 << n); }
int
main (int argc, char *argv[]) {
if (argc < 2 ) {
fprintf (stderr, "Error: insufficient input, usage: %s int\n", argv[0]);
return 1;
}
uint32_t number = (uint32_t)atoi (argv[1]);
uint32_t newnum = number;
int msb = getmsb (number);
int it = 0;
printf ("\n number: %s\n msb : %d\n\n", fmtbinstr_32 (number, 4, "-"), msb);
it = (int)msb;
for (it = 1; it <= msb; it++) {
if ((it % 2) == 0)
bit_clear (&newnum, msb - it);
else
bit_set (&newnum, msb - it);
}
printf (" newnum: %s\n\n", fmtbinstr_32 (newnum, 4, "-"));
return 0;
}
/* return the most significant bit MSB for the value supplied (bit scan reverse)
* for 32-bit values. For 64-bit values, use 'bsrq'.
*/
inline int getmsb (uint32_t x)
{
asm ("bsr %0, %0" : "=r" (x) : "0" (x));
return x;
}
/* binary string of uint32_t x, in szgrp bits groups, separated by sep */
char *fmtbinstr_32 (uint32_t x, const size_t szgrp, char *sep)
{
char b [sizeof(uint32_t) * CHAR_BIT + 1] = {0};
static char fmtb [sizeof (uint32_t) * 2 * CHAR_BIT] = {0};
const size_t len = sizeof(uint32_t) * CHAR_BIT + 1;
register size_t z = 0;
register size_t idx = 0;
if (szgrp > ((len - 1) / 2) || szgrp <= 0) {
fprintf (stderr, "%s() error: invalid input: szgrp '%d' out of range (%d >= szgrp > 0)\n", __func__, (int) szgrp, (int) ((len - 1) / 2));
return NULL; // could make b static and return b instead
}
for (z = 0; z < len - 1; z++)
b [sizeof (uint32_t) * CHAR_BIT - 1 - z] = ((x>>z) & 0x1) ? '1' : '0';
if (sep [0] == '\0') {
fprintf (stderr, "%s() error: invalid input: 'sep' is undefined or empty string\n", __func__);
return NULL;
}
for (z = 0; z < len - 1; z++) {
if ((len - 1 - z) % szgrp == 0 && z > 0) {
fmtb [idx] = sep [0];
idx++;
}
fmtb [idx] = b [z];
idx++;
}
fmtb [idx] = '\0';
return fmtb;
}
output:
$ ./bin/bitalt 10
number: 0000-0000-0000-0000-0000-0000-0000-1010
msb : 3
newnum: 0000-0000-0000-0000-0000-0000-0000-1101
$ ./bin/bitalt 55
number: 0000-0000-0000-0000-0000-0000-0011-0111
msb : 5
newnum: 0000-0000-0000-0000-0000-0000-0011-0101
Basic Version
This version employs the same logic, but leaves out the binary print function and the getmsb function that uses assembler instructions to get the most significant bit. This example uses most of the logic from the original question, but adjust the loops as needed:
#include <stdio.h>
int main (void) {
int i = 0, msb = 0;
unsigned int num = 0;
printf ("\nEnter a number: ");
scanf ("%u", &num);
for (i = 31; i >= 0; i--) {
if (num & 1 << i)
break; // this will give first set bits of num ie 1
} // which is the most significant bit (msb)
msb = i; // save msb
printf ("\n The most significant bit (msb): %d\n", msb);
// we want the index [msb - i] to step down from (msb-1) to 0
// e.g. if num=10, then msb=3, so we want the indexes to be 2,1,0
// so let i start at 1 and we will do (msb -i) until i=msb
for (i = 1; i <= msb; i++) {
if ((i % 2) == 0) // if i mod 2 == 0, we clear the bit
num &= ~(1 << (msb - i)); // clear_bit (make it 0)
else
num |= (1 << (msb - i)); // set_bit (make it 1)
}
printf ("\n The resulting number is: %u\n\n", num);
return 0;
}
output:
$ ./bin/bas
Enter a number: 10
The most significant bit (msb): 3
The resulting number is: 13
$ ./bin/bas
Enter a number: 55
The most significant bit (msb): 5
The resulting number is: 53
I have to shift all bits from x 1 position to the left and the first bit of the left to bit position 0 (most right). I was wondering what I am doing wrong and could you help me with it.
int rotateleft (int x);
int main ()
{
int getal,result;
printf("Enter a number :\n");
scanf("%i",&getal);
result=rotateleft(getal);
printf("result after rotation: %08x", result );
return 0;
}
int rotateleft (int x)
{
int rbit;
rbit = x <<1;
return rbit;
}
From wikipedia:
unsigned int rotl(unsigned int value, int shift) {
return (value << shift) | (value >> (sizeof(value) * CHAR_BIT - shift));
}
Before you do your shifting, get the top bit and save it. Then after the shifting you set that saved bit in the lowest bit in the (shifted) value.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
uint16_t rotate(uint16_t num, uint16_t shBits);
int main(void)
{
uint16_t num = 0x0088, res;
printf("%x\n", num);
res = rotate(num, 3);
printf("%x\n", res);
return 0;
}
uint16_t rotate(uint16_t num, uint16_t shBits)
{
shBits = ( (shBits < 0) ? -shBits : shBits) ; // make sure that n is not a negative number
shBits = shBits % 16; // ensure that the shift value is less than 32
// move shBits most significant bits to the right (LSBs)
// 0x0088 >> (16 - 3) => 0000 0000 0000 0100
// bits = 0000 0000 0000 0100
uint16_t bits = num >> (16 - shBits);
// (num = 0x0088) >> 3 =>0x0011
num >>= shBits;
printf("num %x\n", num);
printf("Bits %x\n", bits);
shBits <<= num; // postion the shifted bints to the right location
num |=shBits;
printf("num %x\n", num);
return (num);
}
Input is 0x0088 (0000 0000 1000 1000)
rotate by 3
Output 0x0011 (0000 0000 0001 0001)
The idea is to use a mask to filer out the left most bit [usually MSB] and save it. Then apply required shift and put back the stored bit in the right most bit location [Usually LSB] shifted value.
In your code, there is one more thing to notice, there is no return statement in int rotateleft (int x) function. After doing all the computation correct, you'll not get the output. Add one return rbit.
int rotateleft (int x)
{
int rbit;
int bit;
bit = !!(x & (1 << 31));
x = x <<1;
x |= bit;
return x;
}
Shift the number by 1 to the left then use the Bitwise OR to add the last bit to the start of the new number:
10000000000010010110100001100010 // i
00000000000100101101000011000100 // i << 1
00000000000000000000000000000001 // i >> 31
| | || | || | |
00000000000100101101000011000101 // (i << 1) | (i >> 31)
So your function will be: Live Demo
unsigned int rotateLeft(unsigned int i)
{
unsigned int j = (i << 1) | (i >> 31);
return j;
}