C++で指定範囲内のセットビット数をカウントする方法
整数値 num と、left(左端)および right(右端)で指定される範囲が与えられます。まず対象の数値を2進数表現に変換し、次に左端の桁から右端の桁まで順に走査して、指定された範囲内に存在するセットビットの個数を計算します。
2進数におけるセットビットとは、「1」で表されるビットのことです。整数値を2進数に変換すると、必ず0と1の組み合わせで表現されます。コンピュータの用語では、この「1」に相当するビットをセットビットと呼びます。
入出力例
入力: int number = 50, left = 2, right = 5
出力: 範囲内のセットビットの合計数は 2
説明: 数値50の2進数表現は「110010」です。left = 2(ビットが1)から始まり、right = 5(ビットが1)で終わる範囲を調べると、その間のビットはすべて0であるため、セットビットの数は2になります。
入力: int number = 42, left = 3, right = 4
出力: 範囲内のセットビットの合計数は 1
説明: 数値42の2進数表現は「101010」です。left = 3 から right = 4 までの範囲内にはセットビットが1つだけ含まれるため、カウントは1になります。
プログラムで使用するアプローチ
- 整数型の変数に数値を入力し、left と right の整数値で範囲を指定します。
- セットビットの合計数を格納するための unsigned int 型変数 count を宣言します。
- i を 1 << 7 から開始し、i > 0 を満たす間、i = i / 2 で更新しながら FOR ループを実行します。
- ループ内では、num & i が真であれば「1」を、偽であれば「0」を出力します。
- 数値が0になるまで、ビットの合計数を計算する while ループを開始します。
- ループ内では count = count + (number & 1) としてカウントを加算し、number >>= 1 で右シフトしていきます。
- 一時変数 a に ((1 << right) - 1) ^ ((1 << (left - 1)) - 1) を設定して、範囲抽出用のマスクを作成します。
- count を count & a で更新し、最終的なカウントを求めます。
- 結果の count を出力します。
マスク生成のポイント
式 ((1 << right) - 1) ^ ((1 << (left - 1)) - 1) は、指定範囲だけを取り出すためのビットマスクを生成しています。(1 << right) - 1 は下位 right ビットがすべて1のマスクを作り、そこから下位 (left - 1) ビットがすべて1のマスクをXORで差し引くことで、left ビット目から right ビット目までだけが1になったマスクが得られます。これにより、範囲外のビットを除外したカウントが可能になります。
C++コード例
#include<iostream>
using namespace std;
// 範囲内の合計ビット数をカウントする関数
unsigned int bits(unsigned int number, unsigned int left, unsigned int right){
unsigned int count = 0;
unsigned i;
// 8ビット表現を表示する
cout<<"8-bit digits of "<<number<<" is: ";
for (i = 1 << 7; i > 0; i = i / 2){
(number & i)? cout<<"1": cout<<"0";
}
// 数値全体のセットビット数を計算する
while (number){
count += number & 1;
number >>= 1;
}
// 指定範囲内のセットビットを計算する
int a = ((1 << right) - 1) ^ ((1 << (left - 1)) - 1);
count = count & a;
cout<<"\nCount of total set bits in a range are: "<<count;
}
int main(){
unsigned int number = 42;
unsigned int left = 2, right = 5;
bits(number, left, right);
return 0;
}
出力結果
上記のコードを実行すると、以下のような出力が得られます。
8-bit digits of 42 is: 00101010 Count of total set bits in a range are: 2
-
C言語で浮動小数点数のセットビット数を数える方法を解説
この問題では、1つの浮動小数点数が与えられ、その2進表現におけるセットビット(1になっているビット)の数を求める必要があります。例えば、浮動小数点数が 0.15625 の場合、セットビットは6個になります。一般的なCコンパイラでは、単精度浮動小数点形式で数値が表現されるため、メモリ上では次のようなビット列として格納されます。考え方:ポインタとバイト単位での処理浮動小数点数をビット値に変換して調べるには、まず対象の数値をポインタ変数に渡し、そのポインタを char* 型にキャストします。こうすることで、float型のデータを1バイトずつ順番に処理できるようになり、各バイト(char型)ごとのセッ
-
C++で集合をk個の部分集合に分割する方法の総数を動的計画法で求める
2つの数 e(要素数) と p(分割数) が与えられたとき、「集合の e 個の要素を p 個の部分集合(パーティション)に分割する方法が全部で何通りあるか」を求めるのがこの問題の目的です。 例1 入力 e=4 p=2 出力 Count of number of ways to partition a set into k subsets are: 7 説明 要素が a・b・c・d の4つである場合、これらを2つのグループに分ける方法は次の7通りあります。 (a)−(b,c,d)、(b)−(a,c,d)、(c)−(a,b,d)、(d)−(a,b,c)、(a,b)−(c,d)、(a,c)−(b,