12

たとえば、2進数unsigned int bin_number = 10101010をその10進表現(つまり170)にできるだけ早く変換する必要がありますか?最高のアルゴリズムは何ですか?

4

5 に答える 5

14

テンプレートを使用すると、コンパイル時にこの問題を解決できます。

template<unsigned long num>
struct binary
{
    static unsigned const value =
        binary<num/10>::value << 1 | num % 10;
};

// Specialization for zero
template<>
struct binary<0>
{ static unsigned const value = 0; };

バイナリ テンプレートは、ゼロに達するnumまで小さい で再度インスタンス化され、特殊化が終了条件として使用されます。num

例:std::cout << binary<10101010>::value;

実行時の問題の場合:

unsigned binary_to_decimal(unsigned num)
{
    unsigned res = 0;

    for(int i = 0; num > 0; ++i)
    {
        if((num % 10) == 1)
            res += (1 << i);

        num /= 10;
    }

    return res;
}
于 2012-06-08T13:10:58.493 に答える
11

この「数値」が、実際に何らかのソース (ファイルまたはユーザーから読み取った) から取得した文字列であり、数値に変換した場合 (実際の数値により適切であると考えて)、その可能性は非常に高くなります。 a を使用std::bitsetして変換を行うことができます。

#include <bitset>

unsigned int number = std::bitset<32>("10101010").to_ulong();

(もちろん、32ここは実装定義であり、より適切には のように記述される可能性がありますstd::numeric_limits<unsigned int>::digits。)

しかし、それが本当に(非常に)最初に数値(整数変数)である場合は、次のことができます。

#include <string>

unsigned int number = std::bitset<32>(std::to_string(bin_number)).to_ulong();

(C++11 を使用to_string) しかし、他の人が数値に基づくより効率的なアルゴリズムを提示しているため、これはおそらく最も効率的な方法ではなくなります。しかし、言ったように、そもそもこの数値を実際の整数変数として実際に取得しているとは思えませんが、テキストファイルまたはユーザーから読み取っています。

于 2012-06-08T13:49:33.853 に答える
4

実際に と書くunsigned int bin_number = 10101010と、これはコンパイラによって 10 進数として解釈されます。

ソース コードにバイナリ リテラルを記述したい場合は、 を使用する必要がありますBOOST_BINARY。次に、を使用して印刷するだけですcout。10進数がデフォルトです...

unsigned int i = BOOST_BINARY(10101010);
std::cout << i; // This prints 170
于 2012-06-08T13:19:37.920 に答える
1

C++11 以降 (その点で C++11 が C++14 よりも制限されている場合でも)、関数はコンパイル時の値を持つconstexpr必要性を回避できます。template

C++14 互換のバージョンは次のとおりです。

constexpr unsigned binary_to_decimal(unsigned num)
{
    unsigned res = 0;

    while (num)
    {
        res = 10 * res + num % 10;
        num /= 10;
    }
    return res;
}

また、リテラルについては、C++14 以降のバイナリ リテラルを使用することもできます。

0b1010'1010 // or 0b10101010 without separator
于 2019-06-13T21:40:39.173 に答える
0

扱っている 2 進数の桁数がわかっていてそれが常に固定さていて、実行時に 2 進数が (ファイルまたは標準入力から読み取られた場合と同様に) 文字列になっている場合 (つまり、コンパイル時の変換が不可能な場合)、次のようにします。このアプローチを採用できます:

int to_binary( const char* c )
{
    return ( ( c[0] & 1 ) ? 0x80 : 0x00 ) |
           ( ( c[1] & 1 ) ? 0x40 : 0x00 ) |
           ( ( c[2] & 1 ) ? 0x20 : 0x00 ) |
           ( ( c[3] & 1 ) ? 0x10 : 0x00 ) |
           ( ( c[4] & 1 ) ? 0x08 : 0x00 ) |
           ( ( c[5] & 1 ) ? 0x04 : 0x00 ) |
           ( ( c[6] & 1 ) ? 0x02 : 0x00 ) |
           ( ( c[7] & 1 ) ? 0x01 : 0x00 );
}

これは固定の 8 桁の 2 進数を想定しています。次のように呼び出されます:

std::cout << to_binary("10101010") << std::endl;

16 ビットの数値がある場合でも、それを使用できます。

const char* bin_number = "1010101010101010";

// Deal with 16 bits
std::cout << ( to_binary( bin_number ) << 8 | to_binary( bin_number + 8 ) ) << std::endl;

ここでは明らかに境界チェックがなく、'1' の LSB は常に 1 であり、'0' は常に 0 であるという事実に依存していることに注意してください (したがって、実際にバイナリ入力であることを検証していません)。

当然のことながら、これは非常に具体的であり、柔軟性は高くありませんが、うまく機能し、はるかに高速になるかどうかはわかりません。

于 2012-06-08T13:57:39.213 に答える