Unsigned Integer to BCD conversion?

前端 未结 10 1060
囚心锁ツ
囚心锁ツ 2020-12-11 05:01

I know you can use this table to convert decimal to BCD:

0 0000

1 0001

2 0010

3 0011

4 0100

5 0101

6 01

相关标签:
10条回答
  • 2020-12-11 05:32

    You know the Binary numeral system, don't you?

    Especially have a look at this chapter.

    EDIT: Also note KFro's comment that the lower nibble (= 4 bits) of the binary ASCII representation of numerals is in BCD. This makes conversions BCD <-> ASCII very easy as you just have to add/remove the leading 4 bits:

    Number    ASCII Code
    0         0011 0000
    1         0011 0001
     ...
    8         0011 1000
    9         0011 1001
    
    0 讨论(0)
  • 2020-12-11 05:34

    I know this has been previously answered but I've extended this for unsigned ints of different sizes using a template to build the specific code.

    #include <stdio.h>
    #include <unistd.h>
    
    #include <stdint.h>
    
    #define __STDC_FORMAT_MACROS
    #include <inttypes.h>
    
    constexpr int nBCDPartLength = 4;
    constexpr int nMaxSleep = 10000; // Wait enough time (in ms) to check out the boundry cases before continuing.
    
    // Convert from an integer to a BCD value.
    // some ideas for this code are from :
    //  http://stackoverflow.com/questions/1408361/unsigned-integer-to-bcd-conversion
    //  &&
    //  http://stackoverflow.com/questions/13587502/conversion-from-integer-to-bcd
    // Compute the last part of the information and place it into the result location.
    // Decrease the original value to place the next lowest digit into proper position for extraction.
    template<typename R, typename T> R IntToBCD(T nValue) 
    {
        int nSizeRtn = sizeof(R);
        char acResult[nSizeRtn] {};
        R nResult { 0 };
        int nPos { 0 };
    
        while (nValue)
        {
            if (nPos >= nSizeRtn)
            {
                return 0;
            }
    
            acResult[nPos] |= nValue % 10;
            nValue /= 10;
    
            acResult[nPos] |= (nValue % 10) << nBCDPartLength;
            nValue /= 10;
    
            ++nPos;
        }
    
        nResult = *(reinterpret_cast<R *>(acResult));
    
        return nResult;
    }
    
    int main(int argc, char **argv)
    {
        //uint16_t nValue { 10 };
        //printf("The BCD for %d is %x\n", nValue, IntToBCD<uint32_t, uint16_t>(nValue));
    
        // UINT8_MAX    =   (255)                               - 2 bytes can be held in uint16_t (2 bytes)
        // UINT16_MAX   =   (65535)                             - 3 bytes can be held in uint32_t (4 bytes)
        // UINT32_MAX   =   (4294967295U)                       - 5 bytes can be held in uint64_t (8 bytes)
        // UINT64_MAX   =   (__UINT64_C(18446744073709551615))  - 10 bytes can be held in uint128_t (16 bytes)
    
    
        // Test edge case for uint8
        uint8_t n8Value { UINT8_MAX - 1 };
        printf("The BCD for %u is %x\n", n8Value, IntToBCD<uint16_t, uint8_t>(n8Value));
        // Test edge case for uint16
        uint16_t n16Value { UINT16_MAX - 1 };
        printf("The BCD for %u is %x\n", n16Value, IntToBCD<uint32_t, uint16_t>(n16Value));
        // Test edge case for uint32
        uint32_t n32Value { UINT32_MAX - 1 };
        printf("The BCD for %u is %" PRIx64 "\n", n32Value, IntToBCD<uint64_t, uint32_t>(n32Value));
        // Test edge case for uint64
        uint64_t n64Value { UINT64_MAX - 1 };
        __uint128_t nLargeValue = IntToBCD<__uint128_t, uint64_t>(n64Value);
        uint64_t nTopHalf = uint64_t(nLargeValue >> 64);
        uint64_t nBottomHalf = uint64_t(nLargeValue);
        printf("The BCD for %" PRIu64 " is %" PRIx64 ":%" PRIx64 "\n", n64Value, nTopHalf, nBottomHalf);
    
        usleep(nMaxSleep);
    
        // Test all the values
        for (uint8_t nIdx = 0; nIdx < UINT8_MAX; ++nIdx)
        {
            printf("The BCD for %u is %x\n", nIdx, IntToBCD<uint16_t, uint8_t>(nIdx));
        }
    
        for (uint16_t nIdx = 0; nIdx < UINT16_MAX; ++nIdx)
        {
            printf("The BCD for %u is %x\n", nIdx, IntToBCD<uint32_t, uint16_t>(nIdx));
        }
    
        for (uint32_t nIdx = 0; nIdx < UINT32_MAX; ++nIdx)
        {
            printf("The BCD for %u is %" PRIx64 "\n", nIdx, IntToBCD<uint64_t, uint32_t>(nIdx));
        }
    
        for (uint64_t nIdx = 0; nIdx < UINT64_MAX; ++nIdx)
        {
            __uint128_t nLargeValue = IntToBCD<__uint128_t, uint64_t>(nIdx);
            uint64_t nTopHalf = uint64_t(nLargeValue >> 64);
            uint64_t nBottomHalf = uint64_t(nLargeValue);
            printf("The BCD for %" PRIu64 " is %" PRIx64 ":%" PRIx64 "\n", nIdx, nTopHalf, nBottomHalf);
        }
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-11 05:35

    Here is a macro for uint16_t, so that it gets evaluated at compile-time (provided that u is a pre-defined constant). This agrees with dec2bcd() from above up to 9999.

    #define U16TOBCD(u) ((((u/1000)%10)<<12)|(((u/100)%10)<<8)|\
                        (((u/10)%10)<<4)|(u%10))
    
    0 讨论(0)
  • 2020-12-11 05:38

    This is from the micro controller world.... Note that values are rounded in the division. For instance 91 to BCD would be 91/10 * 16 = 144 + 91%10 = 145. Converted to Binary is 10010001.

    uint8_t bcdToDec(uint8_t val)
    {
      return ( (val/16*10) + (val%16) );
    }
    
    uint8_t decToBcd(uint8_t val)
    {
      return ( (val/10*16) + (val%10) );
    }
    
    0 讨论(0)
提交回复
热议问题