2014年1月5日日曜日

C++で数値を2進数表記で出力する方法(実行時編)

ビットマスクやデータ構造としてビット列を使用する場合は数値を2進数表記で確認したいことがよくあります。 一番手っ取り早い方法はstd::bitsetでキャストする方法です。

#include <iostream>
#include <bitset>

int main() {
    unsigned x = 11;
    std::cout << static_cast<std::bitset<8> >(x) << std::endl;
}
// 出力結果: 00001011

文字列にしたい場合はstd::stringstreamに入れて、str()を呼びます。

#include <iostream>
#include <sstream>
#include <bitset>

int main() {
    unsigned x = 11;
    std::stringstream ss;
    ss << static_cast<std::bitset<8> >(x);
    std::string x_bin = ss.str();
    std::cout << x_bin << std::endl;
}
// 出力結果: 00001011

桁数指定したくない場合

桁数を自分で指定したくない、先頭のゼロが邪魔という場合は、以下の関数を用意します。

#include <string>
#include <algorithm>

template <typename T>
inline std::string to_bin_str(T n) {
    std::string str;
    while (n > 0) {
        str.push_back('0' + (n & 1));
        n >>= 1;
    }
    std::reverse(str.begin(), str.end());
    return str;
}

処理内容

右端のビットから順に1か0かを調べます。
n & 1とすることで右端のビットを0か1かで抽出し、'0'に加算して'0'か'1'に変換します。
これをstringの末尾に追加していくのですが、このままだと文字列が逆順になってしまうので最後にstd::reverseで文字列を反転します。

使用例

#include <iostream>

int main() {
    char x = 4;
    unsigned y = 11;
    int z = 103;
    unsigned long long w = 4527856554780ULL;
    std::cout << to_bin_str(x) << std::endl;
    std::cout << to_bin_str(y) << std::endl;
    std::cout << to_bin_str(z) << std::endl;
    std::cout << to_bin_str(w) << std::endl;
}

出力結果

100
1011
1100111
1000001111000111001010010000001001100011100

実行時の値で桁を揃えたい場合

std::bitsetによる出力では桁数指定にコンパイル時定数が必要でしたが、実行時の値で桁を揃えたい場合は以下の関数で対応できます。(桁が多い場合は先頭に0埋め、足りない場合は上位ビットを切り捨てます)

#include <string>
#include <algorithm>

template <typename T>
inline std::string to_bin_str(T n, std::size_t digit_num) {
    std::string str;
    while (n > 0) {
        str.push_back('0' + (n & 1));
        n >>= 1;
    }
    str.resize(digit_num, '0');
    std::reverse(str.begin(), str.end());
    return str;
}

使用例

#include <iostream>

int main() {
    char x = 4;
    unsigned y = 11;
    int z = 103;
    unsigned long long w = 4527856554780ULL;
    std::size_t n;
    std::cin >> n;
    std::cout << to_bin_str(x, n) << std::endl;
    std::cout << to_bin_str(y, n) << std::endl;
    std::cout << to_bin_str(z, n) << std::endl;
    std::cout << to_bin_str(w, n) << std::endl;
}

出力結果 (cinでは5を入力)

00100
01011
00111
11100

コンパイル時に2進数表記文字列を生成する方法は次の記事へ。
http://code-mynote.blogspot.jp/2014/01/c2_5.html

1 件のコメント:

  1. 揚げ足取るようですみませんが,「桁数指定したくない場合」のコードが「n==0」を想定していません.

    返信削除