将整数从(纯)二进制转换为BCD

时间:2012-11-06 09:02:46

标签: c binary bcd

我现在愚蠢地解决这个问题......

我得到一个BCD号码(每个数字都是一个自己的4Bit表示)

例如,我想要的是什么:

  • 输入:202(十六进制)== 514(十二月)
  • 输出:BCD 0x415

  • 输入:0x202

  • 位代表:0010 0000 0010 = 514

我尝试了什么:

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

但我知道这是错误的,这将是位表示中的202,然后分成5个半字节,然后再次表示为十进制数

我可以在纸上解决问题,但我不能用一个简单的C代码来解决它

9 个答案:

答案 0 :(得分:8)

你错了路。您的代码正在从 BCD转换为二进制,就像您的问题(原始)标题所示。但是,只有从二进制转换为BCD 时,您提供的输入和输出值才是正确的。在这种情况下,请尝试:

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

证明:http://ideone.com/R0reQh

答案 1 :(得分:2)

尝试以下方法。

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

也可以尝试以下变体(尽管可能效率不高)

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

答案 2 :(得分:1)

这里真正的问题是基地和单位的混乱

202应该是HEX,相当于514十进制......因此BCD计算是正确的

二进制代码十进制将小数(514)转换为三个半字节大小的字段:   - 5 = 0101   - 1 = 0001   - 4 = 0100

更大的问题是你的标题是错误的,你将Uint转换为BCD,而标题要求BCD为Unint

答案 3 :(得分:1)

我的 2 美分,我需要一个类似的 RTC 芯片,它使用 BCD 来编码时间和日期信息。想出了以下可以很好地满足要求的宏:

#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))))

答案 4 :(得分:0)

一个天真但简单的解决方案:

char buffer[16];
sprintf(buffer, "%d", var);
sscanf(buffer, "%x", &var);

答案 5 :(得分:0)

这是我开发的解决方案,适用于嵌入式系统,如Microchip PIC单片机:

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

答案 6 :(得分:0)

这是我的n字节转换版本:

button1 = Button(root, text='Click me', command=change)
button1.pack()

答案 7 :(得分:0)

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

答案 8 :(得分:0)

简单的解决方案

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

二进制:0x202(十进制:514)

BCD:0x514(dec:1300)