Checksum for binary numbers? Converting back to decimal? - c

Introduction
This program should input a number in decimal (base 10) from the user, convert that number to binary, calculate the "binary sum", then present the binary sum and binary representation of the input.
The program should go something like this:
What type of display do you want?
Enter 1 for character parity, 2 for integer checksum: 2
Enter an integer for checksum calculation: 1024
Integer: 1024, Bit representation: 00000000 00000000 00000100 00000000
Sum of the number is: 4
Checksum of the number is: 4, Bit representation: 00000100
What is binary sum?
The "binary sum" of a number, n, is defined splitting the binary representation of n into 8-bit long numbers, and summing the base-10 value of each. This means 32-bit long numbers, you sum the base-10 values of the numbers represented by bits (1-8), (9-16), (17-24), and (25-32). Here is an example:
Example of binary sum of 1234567:
Step 1:
Convert 1234567 into it's binary representation.
1234567 -> 100101101011010000111
Step 2:
Split the binary number into 8 bit parts, adding zero's to the left if needed to make complete 8-bit numbers.
100101101011010000111 -> 00010010 11010110 10000111
Step 3:
Convert each 8-bit long number to decimal then add their values.
00010010 -> 18 (2^1 + 2^4 => 2 + 16 = 18)
11010110 -> 214 (2^1 + 2^2 + 2^4 + 2^6 + 2^7 => 2 + 4 + 16 + 64 + 128) = 214
10000111 -> 135 (2^0 + 2^1 + 2^2 + 2^7 => 1 + 2 + 4 + 128) = 135
18 + 214 + 135 = 367
The binary sum of 1234567 is 367.
I have no problem showing the binary representation of the input, but I'm not sure on how calculate the binary sum. This is challenging because I'm not allowed to use strings or arrays, only basic primitive data types.
This the code I have made so far, with comments where I am having issues:
int main(void) {
char endLoop;
int userChoice;
char choice1;
char byte;
int choice2;
while(endLoop != 'q') {
printf("\nWhat type of display do you want?");
printf("\nEnter 1 for character parity, 2 for integer checksum: ");
scanf("%d", &userChoice);
if(userChoice == 1) {
printf("Enter a character for parity calculation: ");
scanf(" %c", &choice1);
printf("Character: %c" , choice1);
printf(", Bit Representation: ");
int number1s = fromBinary(toBinary(choice1, 8));
printf("\nNumber of ones: %d", number1s);
printf("\nEven 1 parity for the character is: ");
if(number1s % 2 != 0) {
printf("1");
toBinary(choice1, 7);
} else {
toBinary(choice1, 8);
}
}
if(userChoice == 2) {
printf("Enter an integer for checksum calculation: ");
scanf("%d", &choice2);
printf("Integer: %d", choice2);
printf(", Bit Representation: " );
toBinary(choice2, 32);
printf("\nSum of number is: ");
printf("\nChecksum of number is: ");
printf(", Bit Representation: ");
}
printf("\n\nEnter r to repeat, q to quit: ");
scanf(" %c", &endLoop);
}
}
int toBinary(int userInput, int bits) {
int i;
int mask = 1 << bits - 1;
int count = 0;
for (i = 1; i <= bits; i++) {
if (userInput & mask){
count++;
putchar('1');
} else {
putchar('0');
}
userInput <<= 1;
if (! (i % 8)) {
putchar(' ');
}
}
return count;
}
int fromBinary(char binaryValue) {
// I wanted to take the binary value I get from toBinary() and
// convert it to decimal here. But am not sure how to go about it
// since I need the bit representation, and I don't store the bit
// representation, I only print it out.
// I need to convert it to decimal so that I can add the decimal
// values up to calculate the binary sum.
}

EDIT for negative inputs
You have said that you would also like to handle negative numbers. The simplest way to do this, is to define your method to accept an unsigned int rather than an int. This will allow you to do all your normal bit operations without worrying about handling different cases for negative numbers.
Change this line
int getSum(int n) {
to this
int getSum(unsigned int n) {
No further changes are necessary, in fact now we can remove the if statement in getSum.
The new complete getSum method has been updated below. The commented code can be found at the bottom.
Remember, if you want to print out an unsigned int, the format specifier is %u not %d.
Solution
If you have a number, and you want to add up the values of what each 8 bits of that number would be in base 10, you can do it like this:
int getSum(unsigned int n) {
int total = 0;
while(n) {
int tempCount = 0, i = 0;
for(i = 0; n && i < 8; i++) {
tempCount += (n & 1) * pow(2, i);
n >>= 1;
}
total += tempCount
}
return total;
}
Explanation
This code will (while n > 0) grab 8 bits at a time, and add their base-10 values:
2^0 * 1 or 2^0 * 0 +
2^1 * 1 or 2^1 * 0 +
2^2 * 1 or 2^2 * 0 +
... +
2^7 * 1 or 2^7 * 0
tempCount holds the sum for each set of 8 bits, and after each 8 bits, tempCount is added to the total and is reset to 0.
The condition in the for loop, n && i < 8 is of course to stop after grabbing 8 bits, but to also terminate early if n is 0.
Testing
This output:
getSum(1025) = 5
getSum(2048) = 8
getSum(1234567) = 367
getSum(2147483647) = 892
was used to verify the correctness of this code:
#include <stdio.h>
#include <math.h>
int getSum(unsigned int n) {
int total = 0;
//printf("passed in %u\n", n);
while(n) {
int tempCount = 0, i;
//printf("n starts while as %u\n", n);
// Take up to 8 bits from the right side of the number
// and add together their original values (1, 2, 4, ..., 64, 128)
for(i = 0; n && i < 8; i++) {
//printf("\t\tn in for as %u\n", n);
tempCount += (n & 1) * pow(2, i);
//printf("\t\t\tbit is %u\n", (n & 1));
n >>= 1;
}
//printf("\tAdded %u from that set of 8 bits\n", tempCount);
total += tempCount;
}
return total;
}
int main(void) {
printf("getSum(1025) = %d\n", getSum(1025));
printf("getSum(2048) = %d\n", getSum(2048));
printf("getSum(1234567) = %d\n", getSum(1234567));
printf("getSum(2147483647) = %d\n", getSum(2147483647));
return 0;
}
Of course I checked these examples by hand:
2147483647
2147483647 == 01111111 11111111 11111111 11111111
The bit sum =
01111111 + 11111111 + 11111111 + 11111111 =
127 + 255 + 255 + 255 = 892
getSum(2147483647) = 892
1025
1025 == 00000100 00000001
The bit sum =
00000100 + 00000001 =
4 + 1 = 5
getSum(1025) = 5
2048
2048 == 00001000 00000000
The bit sum =
00001000 + 00000000 =
8 + 0 = 8
getSum(2048) = 8
1234567
1234567 == 00010010 11010110 10000111
The bit sum =
00010010 + 11010110 + 10000111 =
18 + 214 + 135 = 367
getSum(1234567) = 367
-1
-1 = 11111111 11111111 11111111 11111111
The bit sum =
11111111 + 11111111 + 11111111 + 11111111 =
255 + 255 + 255 + 255 = 1020
getSum(-1) = 1020

Related

Decimal to binary conversion (8 bit) in C

I've been working on an assignment and so far this is what i've gotten.
int n, c;
printf("Enter a decimal\n");
scanf_s("%d", &n);
printf("%d in binary is: ", n);
for (c = 7; c >= 0; c--)
{
if (n >= 1)
printf("1");
n = n - 1;
else (n < 1)
printf("0");
n = n / 2;
}
I'm new to code and am struggling to figure out where to go from here. Any help would be greatly appreciated.
void printbin(unsigned char val)
{
for(unsigned char i = 0x80; i; i >>= 1)
printf("%c", val & i ? '1' : '0');
printf("\n");
}
Use a bitmask to test if a bit is set. To construct a bitmask one could use bit-shifting:
1 << 0 // shift 1 0 bits to the left: 0b00000001
1 << 1 // shift 1 0 bits to the left: 0b00000010
1 << 2 // shift 1 0 bits to the left: 0b00000100
1 << 3 // shift 1 0 bits to the left: 0b00001000
1 << 4 // shift 1 0 bits to the left: 0b00010000
1 << 5 // shift 1 0 bits to the left: 0b00100000
1 << 6 // shift 1 0 bits to the left: 0b01000000
1 << 7 // shift 1 0 bits to the left: 0b10000000
Then you can use that values to test if a specific bit is set using the bitwise-and operator:
value & (1 << 4) // evaluates to true if bit 5 is set.
// counted 1-based from the right.
To use that to output a 8-bit value:
char unsigned value = 42; // an 8-bit value
for (int bit = 8; bit; --bit) { // count from 8 to 1
putchar(value & (1 << (bit - 1)) ? '1' : '0');
}
First of all you need to know that for conversion from decimal to binary we divide the decimal number repeatedly by 2 and store the reminder and multiply it with the place value so for that we will initialize three variables rem(for storing the reminder) bin(for updating the binary value) place( for getting the place value)
Here is the code for converting decimal to binary value
#include<stdio.h>
#include<string.h>
#include<math.h>
int main()
{
int num,bin=0,place=1,rem;
printf("Enter the number\n");
scanf("%d",&num);
while(num>0)
{
rem =num%2; //Returns the reminder by dividing the number with 2
num =num/2; //Returns the integer value after dividing the number by 2
bin += place*rem; //Store the binary value
place *= 10;
}
printf("The binary number is %d",bin);
}

how can i convert hexadecimal number to binary using bit-mask

int main()
{
double hexa_number;
double bitmask = 0x80;
double i;
printf("Enter 8 bit number in hexadecimal form: ");
scanf("%lf",& hexa_number);
for( i = 0; i <= 8; i++)
{
if(hexa_number&(bitmask >> i))
printf("1");
else
printf("0");
}
return 0;
}
plus Displaying the binary representation of this number,
along with a count of the number of 0’s and 1’s in the binary number.
i found other ways to convert it but not with bitmask
The problem could be that you are using a double for your bitmask. I don't think >> makes much sense for doubles especially as they are composed of a sign bit, mantissa and 2^ exponent.
For example, 8 >> 1 is 4. That is a nice consistent operation, same as division by 2.
If we imagine an unsigned two byte float for simplicity and imagine that the first byte represents the mantissa and the second the exponent (both unsigned), then 7 * 2^4 (=112) could be represented as 0b00000111 00000100. If you shift that 1 to the right, >> 1, you will get 0b00000011 10000010, which by our convention is now 3 * 2^130. This is definitely not the division by 2 you would get by shifting an integer right by 1.
My compiler gives "error: invalid operands to binary >> (have double and unsigned)" if I try bitwise shifting a floating point number.
So basically you could try the following:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int hexa_number = 0;
unsigned num_bits = sizeof(int)*8;
unsigned bitmask = 1 << (num_bits - 1);
printf("Enter a number in hexadecimal form: ");
scanf("%i", &hexa_number);
unsigned k = 0;
unsigned num_ones = 0;
unsigned num_zeros = 0;
for(k = 0; k != num_bits; k ++)
{
if(hexa_number & (bitmask >> k))
{
printf("1");
num_ones ++;
}
else
{
printf("0");
num_zeros++;
}
}
printf("\nNumber of ones is %i\nNumber of zeros is %i", num_ones, num_zeros);
return 0;
}

Logic to set a bits of given number from first occurance of bits 1 as given example?

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

Count number of bits in an unsigned integer

I want to write a function named bitCount() in the file: bitcount.c that returns the number of bits in the binary representation of its unsigned integer argument.
Here is what I have so far:
#include <stdio.h>
int bitCount (unsigned int n);
int main () {
printf ("# 1-bits in base 2 representation of %u = %d, should be 0\n",
0, bitCount (0));
printf ("# 1-bits in base 2 representation of %u = %d, should be 1\n",
1, bitCount (1));
printf ("# 1-bits in base 2 representation of %u = %d, should be 16\n",
2863311530u, bitCount (2863311530u));
printf ("# 1-bits in base 2 representation of %u = %d, should be 1\n",
536870912, bitCount (536870912));
printf ("# 1-bits in base 2 representation of %u = %d, should be 32\n",
4294967295u, bitCount (4294967295u));
return 0;
}
int bitCount (unsigned int n) {
/* your code here */
}
Okay, when I just run this I get:
# 1-bits in base 2 representation of 0 = 1, should be 0
# 1-bits in base 2 representation of 1 = 56, should be 1
# 1-bits in base 2 representation of 2863311530 = 57, should be 16
# 1-bits in base 2 representation of 536870912 = 67, should be 1
# 1-bits in base 2 representation of 4294967295 = 65, should be 32
RUN SUCCESSFUL (total time: 14ms)
It doesn't return the correct numbers of bits.
What's the best way to return the number of bits in the binary representation of its unsigned integer argument in C?
Here's a solution that doesn't need to iterate. It takes advantage of the fact that adding bits in binary is completely independent of the position of the bit and the sum is never more than 2 bits. 00+00=00, 00+01=01, 01+00=01, 01+01=10. The first addition adds 16 different 1-bit values simultaneously, the second adds 8 2-bit values, and each one after does half as many until there's only one value left.
int bitCount(unsigned int n)
{
n = ((0xaaaaaaaa & n) >> 1) + (0x55555555 & n);
n = ((0xcccccccc & n) >> 2) + (0x33333333 & n);
n = ((0xf0f0f0f0 & n) >> 4) + (0x0f0f0f0f & n);
n = ((0xff00ff00 & n) >> 8) + (0x00ff00ff & n);
n = ((0xffff0000 & n) >> 16) + (0x0000ffff & n);
return n;
}
This is hard-coded to 32 bit integers, if yours are a different size it will need adjusting.
int bitCount(unsigned int n) {
int counter = 0;
while(n) {
counter += n % 2;
n >>= 1;
}
return counter;
}
Turns out there are some pretty sophisticated ways to compute this as answered here.
The following impl (I learned way back) simply loops knocking off the least significant bit on each iteration.
int bitCount(unsigned int n) {
int counter = 0;
while(n) {
counter ++;
n &= (n - 1);
}
return counter;
}

Convert integer from (pure) binary to BCD

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;
}

Resources