Ammar
Ammar

Reputation: 1233

How to convert BCD to decimal?

How can I convert a binary-coded decimal number into a decimal number in terms of representation ? I don't want to convert the value of it but rather the representation of it, here is what I mean.

I want to convert 0x11 to decimal 11 (not 17) and 0x20 to 20 (not 32).

unsigned char day = 0x11;
unsigned char month = 0x12;

int dayDecimal, monthDecimal;

I want dayDecimal to be 11 and monthDecimal = 12. I will be working with a range between 0x00 to 0x60 so it should be possible. There won't be 'A', 'B', 'C', 'D', 'E', 'F.

Update:

I am actually reading time from an RTCC chip as part of an embedded project I am working on. The hours, minutes, day, and month are returned in that form. For example if minutes are 0x40 then it means 40 minutes and not 64, so I need to able to keep the interpretation of it correctly. I need somehow to convert 0x40 into 40 and not 64. I hope that's possible.

Thanks!

Upvotes: 12

Views: 43789

Answers (3)

kavya gupta
kavya gupta

Reputation: 11

Put the desired value in the function and you will get an integer in return.

#include <stdio.h>
#include <math.h>

typedef int                 INT32;

typedef short int           INT16;

typedef unsigned short int  UINT16;

typedef unsigned long int   UINT32;

UINT32 BCDToDecimal(UINT32 nDecimalValue){
    UINT32 nResult=0;
    INT32  nPartialRemainder, ncnt,anHexValueStored[8];
    UINT16 unLengthOfHexString = 0,unflag=0;

    for(ncnt=7 ;ncnt>=0 ; ncnt--){
        anHexValueStored[ncnt]=nDecimalValue & (0x0000000f << 4*(7-ncnt));
        anHexValueStored[ncnt]=anHexValueStored[ncnt] >> 4*(7-ncnt);
        if(anHexValueStored[ncnt]>9)
        unflag=1;
    }
    if(unflag==1){
        return 0;
    }
    else{
        for(ncnt=0 ;ncnt<8 ; ncnt++)
        nResult= nResult +anHexValueStored[ncnt]*pow(10,(7-ncnt));
        return nResult;
    }
}
int main() {
    printf("%ld\n",BCDToDecimal(0X20));
    return 0;
}

Upvotes: 1

chqrlie
chqrlie

Reputation: 144695

A very simple method without error checking:

int bcd_to_decimal(unsigned char x) {
    return x - 6 * (x >> 4);
}

Upvotes: 15

Jonathan Leffler
Jonathan Leffler

Reputation: 753605

You need to work with the two nybbles, multiplying the more significant nybble by ten and adding the less significant:

uint8_t hex = 0x11;
assert(((hex & 0xF0) >> 4) < 10);  // More significant nybble is valid
assert((hex & 0x0F) < 10);         // Less significant nybble is valid
int dec = ((hex & 0xF0) >> 4) * 10 + (hex & 0x0F);

If the assertions are disabled but the input is bogus (e.g. 0xFF), you get what you deserve: GIGO — garbage in, garbage out. You can easily wrap that into an (inline) function:

static inline int bcd_decimal(uint8_t hex)
{
    assert(((hex & 0xF0) >> 4) < 10);  // More significant nybble is valid
    assert((hex & 0x0F) < 10);         // Less significant nybble is valid
    int dec = ((hex & 0xF0) >> 4) * 10 + (hex & 0x0F);
    return dec;
}       

This conversion is reminiscent of BCD — Binary Coded Decimal.

Upvotes: 19

Related Questions