C++で指定範囲内の未セットビット(0ビット)の個数を数える方法
整数値 num と、left(左端)・right(右端)の2つの値で表される範囲が与えられたとします。まず対象となる数値を2進数に変換し、続いて左端の桁から右端の桁までループ処理を行い、その範囲内に含まれる「未セットビット(unset bit)」の個数を求めるのが本記事の課題です。
2進数における未セットビットとは、値が「0」になっているビットのことです。整数値を2進数へ変換すると、必ず0と1の組み合わせで表現されます。コンピュータの用語としては、この「0」にあたるビットが未セットビットと呼ばれます。
入出力例
入力: int number = 50, left = 2, right = 5
出力: 範囲内の未セットビットの合計数は 2
説明: 数値50の2進表現は「110010」です。範囲は left = 2 の桁(ビットが1)から始まり、right = 5 の桁(ビットが1)で終わります。この範囲の間には0が2つあるため、未セットビットの数は2となります。
入力: int number = 42, left = 1, right = 6
出力: 範囲内の未セットビットの合計数は 3
説明: 数値42の2進表現は「101010」です。範囲は left = 1 の桁(ビットが1)から始まり、right = 6 の桁(ビットが0)で終わります。この範囲内には0が3つあるため、カウントは3となります。
プログラムで使用するアプローチ
- 整数型の変数に数値を入力するとともに、left と right の整数値で範囲を指定します。
- セットビットの合計数を保持するための unsigned int 型変数 count を宣言します。
- i を 1 << 7 で初期化し、i > 0 の間、i を i / 2 ずつ減らしながら繰り返す for ループを開始します。
- ループ内では各ビットを判定し、1であれば「1」を、0であれば「0」を出力します。これにより数値の8ビット表現が表示されます。
- i を left から right まで1ずつ増やしながら繰り返す for ループを開始します。
- ループ内で、指定範囲に含まれるビットの総数をカウントアップしていきます。
- 数値が0になるまで処理を続ける while ループで、数値全体のセットビット数を計算します。
- ループ内では count = count + (number & 1) としてセットビットを加算し、number >>= 1 で数値を1ビット右シフトします。
- 一時変数 a を ((1 << right) - 1) ^ ((1 << (left - 1)) - 1) として設定します。これは指定範囲だけを取り出すためのマスクになります。
- 続いて、count を count & a として更新します。
- 最後に、count を「範囲内のビット総数 − 範囲内のセットビット数」として計算すれば、未セットビットの個数が求まります。
コード例
#include<iostream>
using namespace std;
//範囲内の未セットビットの合計数を求める関数
unsigned int unset_bits(unsigned int number, unsigned int left, unsigned int right){
unsigned int count = 0;
unsigned int total_bits = 0;
unsigned i;
//8ビットの2進表現を表示
cout<<"8-bit number of "<<number<<" is: ";
for (i = 1 << 7; i > 0; i = i / 2){
(number & i)? cout<<"1": cout<<"0";
}
//指定範囲内のビット数を計算
for(i = left; i<=right; i++){
total_bits++;
}
//数値全体のセットビット数を計算
while (number){
count += number & 1;
number >>= 1;
}
//範囲内のセットビットを抽出するマスクを作成
int a = ((1 << right) - 1) ^ ((1 << (left - 1)) - 1);
count = count & a;
//範囲内のビット総数からセットビット数を差し引く
count = total_bits - count;
cout<<"\nCount of total unset bits in a range are: "<<count;
}
int main(){
unsigned int number = 80;
unsigned int left = 1, right = 4;
unset_bits(number, left, right);
return 0;
}
出力
上記のコードを実行すると、次のような結果が出力されます。
8-bit number of 80 is: 01010000 Count of total unset bits in a range are: 2
まとめ
本記事では、C++を用いて整数の指定範囲内に存在する未セットビット(0ビット)の個数を求める方法を解説しました。ポイントは、((1 << right) - 1) ^ ((1 << (left - 1)) - 1) という式で範囲を抽出するマスクを作成し、ビット演算を組み合わせることで目的のビットだけを効率よく扱える点です。2進数の考え方とビット操作に慣れておくと、この種の問題はスムーズに解けるようになります。
-
【C++】長方形に含まれる正方形の総数を求めるアルゴリズムと実装
縦の長さL、横の幅B(L≥B)の長方形が与えられたとします。この記事では、L×Bの長方形の中にいくつの正方形が含まれているかを効率的に求める方法を解説します。 上の図は3×2の長方形の例です。この長方形には、2×2の正方形が2個、1×1の正方形が6個含まれています。 合計:6+2=8個 規則性を見つける まず、正方形だけで構成されたB×Bの図形について考えてみましょう。 サイズL×Bの長方形には、必ずL×B個の1×1の正方形が含まれます。 含まれる最大の正方形のサイズはB×Bです。 L=B=1の場合:正方形の数=1 L=B=2の場合:正方形の数=1+4=5(2×2が1個、1×1が4個) L
-
指定した範囲内の未設定ビットを数えるPythonプログラム
正の整数とビット位置の範囲が与えられたとき、その範囲内に含まれる未設定ビット(値が「0」のビット)の個数を数える方法を解説します。 入力 : n = 50, 開始位置 = 2, 終了位置 = 5 出力 : 2 この例では、ビット位置2から5の範囲内に「0」のビットが2つ存在します。実際、50を2進数で表すと 110010 となり、下位から数えて3番目(位置2)と6番目(位置5)に該当する部分に「0」が2つ含まれています。 アルゴリズム bin() 関数を使って、整数 n を2進数の文字列に変換します。 先頭の2文字(プレフィックス 0b)を取り除きます。 文字列を反転させます。これにより