7

このテーブルを使用して、10 進数を BCD に変換できることはわかっています。

0 0000

1 0001

2 0010

3 0011

4 0100

5 0101

6 0110

7 0111

8 1000

9 1001

この変換の式はありますか、それとも表を使用する必要がありますか? この変換用のコードを書き込もうとしていますが、その計算方法がわかりません。提案?

4

10 に答える 10

8

2進数システムを知っていますよね?

特にこの章を見てください。

編集: 数値のバイナリ ASCII 表現の下位ニブル (= 4 ビット) は BCD であるという KFro のコメントにも注意してください。これにより、先頭の 4 ビットを追加/削除するだけでよいため、BCD <-> ASCII への変換が非常に簡単になります。

数値 ASCII コード
0 0011 0000
1 0011 0001
 ...
8 0011 1000
9 0011 1001
于 2009-09-11T00:04:12.157 に答える
6

これはマイクロコントローラの世界からのものです....値は除算で丸められていることに注意してください。たとえば、91 を BCD に変換すると、91/10 * 16 = 144 + 91%10 = 145 になります。バイナリに変換すると、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) );
}
于 2012-02-07T01:31:23.523 に答える
5

通常、誰かが 10 進数から BCD に変換したいと言うとき、彼らは複数の 10 進数について話しているのです。

BCD は、多くの場合、1 バイトあたり 2 桁の 10 進数にパックされます (お示しのように、0..9 は 4 ビットに収まるため)、10 進数あたり 1 バイトの配列を使用する方が自然だと思います。

n ビットの符号なし 2 進数は、ceil(n*log_2(10)) = ceil(n/log10(2)) の 10 進数に収まります。2^3=8 は 10 より小さいため、ceil(n/3) = floor((n+2)/3)) の 10 進数にも収まります。

それを念頭に置いて、unsigned int の 10 進数を取得する方法は次のとおりです。

#include <algorithm>
#include <vector>

template <class Uint>
std::vector<unsigned char> bcd(Uint x) {  
  std::vector<unsigned char> ret;
  if (x==0) ret.push_back(0); 
  // skip the above line if you don't mind an empty vector for "0"
  while(x>0) {
    Uint d=x/10;
    ret.push_back(x-(d*10)); // may be faster than x%10
    x=d;
  }
  std::reverse(ret.begin(),ret.end());
  // skip the above line if you don't mind that ret[0] is the least significant digit
  return ret;
}

もちろん、int 型の幅がわかっている場合は、固定長の配列を好むかもしれません。0 番目の桁が最下位であり、入力/出力でのみ反転するという事実を思い出すことができれば、反転する理由もまったくありません。最下位桁を最初の桁として保持すると、固定桁数を使用しない場合の桁単位の算術演算が簡素化されます。

「0」を空の数字列ではなく、単一の「0」10 進数として表したい場合 (どちらも有効)、特に x==0 をチェックします。

于 2009-09-11T00:31:35.583 に答える
2

1 バイトあたり 2 桁の 10 進数が必要で、「unsigned」が「unsigned long」の半分のサイズである場合 (必要に応じて uint32 および uint64 typedef を使用します):

unsigned long bcd(unsigned x) {
  unsigned long ret=0;
  while(x>0) {
    unsigned d=x/10;
    ret=(ret<<4)|(x-d*10);
    x=d;
  }
  return ret;
}

This leaves you with the least significant (unit) decimal digit in the least significant half-byte. You can also execute the loop a fixed number (10 for uint32) of times, not stopping early when only 0 bits are left, which would allow the optimizer to unroll it, but that's slower if your numbers are often slow.

于 2009-09-11T00:39:22.383 に答える
0

このようなものはあなたの変換に役立ちますか?

#include <string>
#include <bitset>

using namespace std;

string dec_to_bin(unsigned long n)
{
    return bitset<numeric_limits<unsigned long>::digits>(n).to_string<char, char_traits<char>, allocator<char> >();
}
于 2009-09-11T00:12:12.590 に答える
0

これは以前に回答されていることは知っていますが、テンプレートを使用してさまざまなサイズの符号なし int に拡張し、特定のコードを作成しました。

#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;
}
于 2017-01-11T18:58:26.997 に答える