2進数・ビット・容量|論理・アルゴリズム・情報の基礎
このページはプロモーション(広告)を含みます。
論理・アルゴリズム・情報の基礎(初級・読む25分+演習30分)
この授業のゴール
- ビット数から表せる値の数(2のn乗)を計算し、必要なビット数を求められる
- 2進数と10進数を相互に変換し、1バイトで表せる整数の範囲(0〜255)を説明できる
- 行数と1行のバイト数からデータ容量を見積もり、1,000倍の単位と1,024倍の単位を区別できる
- 小数が2進数で正確に表せないことを実行結果で確かめ、等しさの比較を安全に書ける
仕事でどう使うか
データの仕事では、「このデータは何GBか」「このID列は何桁あれば足りるか」「整数の列を小さい型に変えてよいか」を判断する場面が頻繁にあります。計算機の中の値は、すべて0と1の並びで保存されるため、その性質を知っていると、容量の見積もりと、不思議な計算結果の理由がわかります。
| 路線 | この授業の使いどころ |
|---|---|
| DS(データサイエンティスト) | データの読み込み前に、行数×列数×1値のバイト数でメモリを見積もる。0.1+0.2 のような浮動小数点の誤差を理解する |
| ML(機械学習エンジニア) | 精度(32ビット・16ビットの浮動小数点)と、メモリ・速度のトレードオフを説明する。画像を0〜255の整数で扱う理由がわかる |
| DX(DX推進・AI企画) | システム導入時に、保存するデータ量とクラウド費用を見積もる。ID体系(何桁・何種類)の設計に使う |
| RS(研究者) | 実験データの保存量と、記録できる数値の精度(有効な桁数)を設計する |
この授業のゴールは、ビット・バイト・容量を数値で計算し、見積もりの根拠として説明できるようになることです。
前提
次の言葉と操作を使います。不安があれば先に戻ってください。
- 累乗(2を3回かける $2^3=8$)と、指数 → 四則計算と計算順序、文字式と代入
- 単位と桁と丸め(1,000倍の接頭辞:K、M、G)→ 単位と桁と丸め
- 型(整数
int、小数float、文字列str)→ 数値・文字列・真偽値 - 手順と繰り返し(割り算を繰り返す手順)→ 手順・分岐・繰り返し
コードは、画面内の 実行 ボタンで動かせます。実行前に、結果を予想してください。
身近な状況:4つのスイッチで、何通りの状態を表せるか
部屋の壁に、ON/OFFの切り替えスイッチが4個並んでいます。各スイッチは、ONかOFFの2通りです。4個全体では、何通りの並びがあるでしょうか。
1個目が2通り、2個目が2通り、…と続くので、全体は 2×2×2×2=16通りです。ONを1、OFFを0と書くと、「0000」から「1111」までの16個の並びになります。
コンピュータの中のスイッチ1個にあたるものがビット(bit)で、0か1の2通りの値を持ちます。ビットがいくつか集まると、表せる並びの数は次のように増えます。
for n in range(1, 11):
print(f'{n:2} ビット → {2 ** n:5} 通り')
出力のとおり、1ビット増えるごとに2倍になります。会員区分(一般・会員・プレミアムの3種類)を数値で表すなら、2ビットあれば4通りまで表せるので足ります(1ビットは2通りで足りません)。
この「何通り表せるか」という考え方が、容量の見積もりやIDの桁数の設計の出発点です。この授業では、このスイッチの比喩を、正確な数と記号で整理します。
直感的な説明:位取りの考え方は、10進数も2進数も同じ
ふだん使う10進数は、桁が1つ上がるごとに10倍の重みが付く位取りです。たとえば 473 は、4×100+7×10+3×1 です。
2進数は、重みが10倍ではなく2倍になる位取りです。右から順に、1、2、4、8、16、… の重みが付きます。2進数の 1011 を、10進数に直しましょう。
| 桁(左から) | 1 | 0 | 1 | 1 |
|---|---|---|---|---|
| 重み | 8 | 4 | 2 | 1 |
| 1の桁の重みを足す | 8 | (なし) | 2 | 1 |
8+2+1=11 です。つまり、2進数の1011は、10進数の11と同じ大きさです。
逆に、10進数を2進数に直すには、2で割った余りを順に並べます。11を2で割ると商5・余り1、5を2で割ると商2・余り1、2を2で割ると商1・余り0、1を2で割ると商0・余り1。余りを下から上へ読むと 1011 です。
たとえ話の限界:スイッチの比喩は「並びの数」を数えるためのものです。実際のコンピュータは、数、文字、画像、色などを、すべてビットの並びに約束事(符号化)で対応させています。同じビットの並びでも、整数として読むか、文字として読むかで意味が変わります。
正確な定義:ビット・バイト・範囲・容量の単位
用語と計算式を、正確に定義します。
- ビット(bit):0か1のどちらかを表す、情報の最小単位。
- バイト(byte):8ビットのまとまり。$2^8=256$ 通りを表せる。
- $n$ ビットで表せる値の数は $2^n$ 通り。
- 符号なし整数(0以上だけを表す整数)の範囲:0 から $2^n-1$ まで。1バイトなら 0〜255(最大値は256ではない)。
- 符号付き整数(負の数も表す整数)の範囲:$-2^{n-1}$ から $2^{n-1}-1$ まで。1バイトなら −128〜127。
$n$ はビット数(個)、$2^n$ は通り数(個)です。$n=8$ を代入すると $2^8 = 2\times2\times2\times2\times2\times2\times2\times2 = 256$ です。256通りのうち、0を1つ目に数えるので、最大値は 255 です。
必要なビット数:$k$ 種類を区別するのに必要な最小のビット数 $n$ は、$2^n \ge k$ を満たす最小の整数です。100種類なら、$2^6=64$ では足りず、$2^7=128$ で足りるので、$n=7$ です。
次のコードは、Python で2進数と10進数を相互に変換します。bin(x) は整数 x を '0b' から始まる2進数の文字列に直し、int(s, 2) は2進数の文字列を整数に直します。
x = 11
print(bin(x)) # '0b1011'
print(format(x, 'b')) # '1011'(0b なし)
print(int('1011', 2)) # 11
print((100 - 1).bit_length()) # 100種類を区別するのに必要なビット数
bit_length() は、整数を表すのに必要な2進数の桁数を返します。0〜99の100個を表すとき、最大値99は2進数で7桁(1100011)なので、必要なビット数は7です。
容量の見積もり:データの容量は、次の式で見積もります。
$$\text{容量(バイト)}=\text{行数}\times\text{1行のバイト数}$$
単位の違い:1,000倍ごとの接頭辞(K、M、G)では、1KB=1,000バイト(10の3乗)とするのが国際単位系(SI)の使い方です。一方、1,024倍(2の10乗)を表す正式な単位として、KiB、MiB、GiB(キビバイト、メビバイト、ギビバイト)があります。1MiB=1,048,576バイト、1GiB=1,073,741,824バイトです。ソフトウェアやOSによって、同じ「GB」が1,000倍の意味だったり1,024倍の意味だったりします。これは執筆時点(2026年)の一般的な説明で、使っている製品の表記は仕様書で確認してください。
段階付き例題:会員データの容量を見積もる
問題:会員データが1,000,000行あります。1行は、会員ID(8バイト)、登録日(8バイト)、会員区分(4バイト)、氏名(最大100バイト)の合計120バイトで保存されます。全体の容量を見積もってください。
ステップ1:式を決める。容量(バイト)=行数×1行のバイト数。
ステップ2:代入する。1,000,000×120=120,000,000バイトです。
ステップ3:単位を決める。1MB=1,000,000バイトとすると、120,000,000÷1,000,000=120MB。1MiB=1,048,576バイトとすると、120,000,000÷1,048,576≒114.4MiB。同じバイト数でも、使う単位で数字が変わります。
rows = 1_000_000
bytes_per_row = 8 + 8 + 4 + 100
total = rows * bytes_per_row
print('1行', bytes_per_row, 'バイト')
print('合計', total, 'バイト')
print('MB (1000倍) :', total / 1000 ** 2)
print('MiB (1024倍) :', round(total / 1024 ** 2, 1))
ステップ4:氏名の保存を点検する。氏名が日本語の場合、文字コードによって1文字のバイト数が違います。UTF-8(世界中の文字を扱える文字コードの1つ)では、英数字は1バイト、ひらがなや漢字は通常3バイトです。
for s in ['abc', 'あいう', '山田太郎']:
print(s, len(s), '文字', len(s.encode('utf-8')), 'バイト')
出力は、abc が3文字3バイト、あいう が3文字9バイト、山田太郎 が4文字12バイトです。「100バイト」は、日本語なら約33文字ぶんです。
ステップ5:結果を読む。この見積もりは、データベースの内部構造(索引や管理領域)やバックアップを含みません。実際の保存容量は、見積もりより大きくなります。見積もりは、桁(数十MBか数十GBか)を知るために使います。
ステップ6:意味を言葉に戻す。「100万行の会員表は、1行120バイトで約120MB。氏名の最大長が変わると容量も変わる」。根拠の式と前提(1行のバイト数)を一緒に書くと、他の人が検証できます。
操作して理解する:範囲・必要ビット数・あふれを試す
次のコードは、ビット数ごとの整数の範囲と、値が範囲を超えたとき(あふれ)の様子を示します。実行する前に、8ビットの符号なし整数で 255 に1を足すと何になるか予想してください。
for n in [8, 16, 32]:
print(f'{n:2} ビット 符号なし 0 〜 {2 ** n - 1:>13,}')
print(f'{n:2} ビット 符号付き {-2 ** (n - 1):>13,} 〜 {2 ** (n - 1) - 1:>13,}')
# 8ビットの符号なし整数は 256 通り。範囲を超えると、先頭に戻る(256で割った余り)
v = 255
print('255 + 1 =', (v + 1) % 256)
print('200 + 100 =', (200 + 100) % 256)
予想と答え:
- 8ビット符号なしで 255+1 は、256通りを一周して 0 に戻ります。200+100=300 は、300−256=44 になります。
- 画像の明るさを0〜255の整数で保存するのは、1ピクセル1バイトで足りるためです。255を超える計算をする前には、より大きい型に変える必要があります。
次に、自分で書き換えてみましょう。
- 年齢(0〜120歳)を保存するには、符号なし整数で何ビットあれば足りますか。
- 日本の全人口(約1.2億人)にIDを振るには、最低何ビット必要ですか。
答えは、(1) 121通りが必要で、$2^7=128$ なので 7ビット。(2) 約1.2億(1.2×10⁸)は、$2^{26}=67{,}108{,}864$ では足りず、$2^{27}=134{,}217{,}728$ で足りるので 27ビットです。実務では、ID体系に余裕を持たせて、32ビット(約42.9億通り)などを使います。
注意:「必要なビット数」は理論上の最小値です。実際のデータベースは、1バイト単位(8ビット、16ビット、32ビット、64ビット)で整数の型を選びます。
発展:浮動小数点の誤差・符号付き整数・文字コード
浮動小数点数:小数は、2進数の「仮数部×2の指数」の形で保存されます(浮動小数点数、Python の float)。10進数の0.1は2進数では無限に続く小数になり、有限のビット数で保存すると近似値になります。そのため、0.1 + 0.2 は 0.3 とわずかに異なります。お金のように、1円未満の誤差を許さない計算では、整数(円単位)や、10進数を正確に扱う型を使います。
符号付き整数:負の数は、多くの場合、「2の補数」という方法で保存されます。8ビットなら、0〜127を0と正の数(0〜127)、128〜255を −128〜−1 に対応させます。範囲が −128〜127 になる理由はこの割り当てです。
精度とビット数の関係:機械学習では、重みを32ビットの浮動小数点から16ビットに減らすと、メモリは半分になりますが、表せる桁数が減ります。容量・速度・精度のトレードオフであり、どれを優先するかは、目的で決まります。
ハッシュとID:IDを短くするほど衝突(別の対象が同じIDになる)の確率が上がります。必要なビット数の見積もりは、「全件を区別できる」理論上の最小値ですが、ランダムなIDでは余裕を大きく取る必要があります。
圧縮と容量:圧縮をかけると、保存される容量は小さくなります。圧縮率はデータの性質で変わり、事前に確定できません。見積もりは、まず圧縮なしで計算し、実測で確認します。全件を読む費用の考え方は 計算量と小さい反例 で扱います。
よくある失敗
失敗1:1,000倍の単位と1,024倍の単位を混ぜて、見積もりがずれる
10GB(1,000倍系)のデータを、「10GiB(1,024倍系)の空き領域に入るか」で判断する場面です。同じ「10」でも、単位が違えば大きさが違います。
data_bytes = 10 * 1000 ** 3 # 10GB(1000倍の単位)
print('10GB のバイト数:', data_bytes)
print('GiB 換算 :', round(data_bytes / 1024 ** 3, 3), 'GiB')
print('差の割合 :', round((1 - data_bytes / (10 * 1024 ** 3)) * 100, 1), '%')
10GB(10×10⁹バイト)は約9.313GiBで、10GiBより約6.9%少なくなります(10GiBを基準にした差)。逆にGBを基準にすると、1GiBは1GBより約7.4%大きい単位です。単位の接頭辞が大きくなるほど、1,000倍と1,024倍の差は広がります(GBを基準にすると、KBでは2.4%、GBでは約7.4%)。
直し方:容量を書くときは、単位が1,000倍系(KB・MB・GB)か1,024倍系(KiB・MiB・GiB)かを、必ず確認して併記する。見積もりでは、バイト数まで落としてから単位を換算する。
失敗2:小数の等しさを `==` で比べて、予想と違う結果になる
0.1+0.2が0.3と等しいかを、そのまま比べた例です。
a = 0.1 + 0.2
print(a)
print(a == 0.3)
print(abs(a - 0.3) < 1e-9)
print(format(0.1, '.20f'))
出力は、0.30000000000000004、False、True、0.10000000000000000555 です。0.1は2進数で無限小数になるため、保存された値は近似値で、足し算の結果にも微小な誤差が残ります。
直し方:小数の等しさは、「差の絶対値が十分小さい」かで判定する(abs(a - b) < 1e-9)。お金の計算は、円単位の整数で行う。誤差は「バグ」ではなく、保存方式の性質です。
失敗3:必要なビット数を、種類数の割り算で求めてしまう
100種類を区別するのに必要なビット数を、「100÷2=50ビット」や「100÷8=12.5ビット」と考えてしまう誤りです。正しくは、$2^n \ge 100$ を満たす最小の $n$ です。
k = 100
for n in range(1, 10):
ok = 2 ** n >= k
print(n, 'ビット →', 2 ** n, '通り', '足りる' if ok else '足りない')
if ok:
break
print('bit_length で確認:', (k - 1).bit_length())
6ビットは64通りで足りず、7ビット(128通り)で足ります。ビットが1つ増えると通り数は2倍になる(足し算ではなく、かけ算で増える)ので、割り算では求まりません。また、$2^7=128$ ぴったりのときの境界にも注意が必要です。128種類なら7ビット、129種類なら8ビットです。
直し方:種類数 $k$ に対して、$(k-1)$ を2進数にしたときの桁数((k-1).bit_length())が必要なビット数。0から数えるため、$k$ ではなく $k-1$ を使います。
まとめ
- nビットで表せる値の数は $2^n$ 通り。1ビット増えるごとに2倍になる。k種類を区別する最小のビット数は、$2^n \ge k$ を満たす最小の n。
- 1バイトは8ビットで256通り。符号なしなら0〜255、符号付きなら−128〜127。範囲を超えると、あふれる。
- 容量=行数×1行のバイト数。1,000倍系(KB・MB・GB)と1,024倍系(KiB・MiB・GiB)を区別して併記する。
- 小数は2進数で近似して保存される。
0.1 + 0.2 == 0.3は False。差が十分小さいかで比べる。
用語
- ビット(bit)
0か1のどちらかを表す、情報の最小単位。
- バイト(byte)
8ビットのまとまり。256通りの値を表せる。
- 2進数(binary number)
桁が上がるごとに重みが2倍になる位取りの数。0と1だけで書く。
- KiB・MiB・GiB(kibibyte, mebibyte, gibibyte)
1,024倍ごとの容量の単位。1MiB=1,048,576バイト。1,000倍系のKB・MB・GBと区別する。
- 浮動小数点数(floating-point number)
小数を、仮数と指数の形で近似して保存する数。Pythonのfloat。
よくある質問
なぜコンピュータは10進数ではなく2進数を使うのですか?
電気回路では、オンとオフの2状態を確実に区別するのが、最も簡単で誤りにくいからです。2状態の組み合わせで、数も文字も画像も表せます。人間が読みやすいように、画面では10進数や16進数で表示されます。
16進数は、何のために使うのですか?
2進数の4桁を、1桁(0〜9、A〜F)で表せるので、長い2進数を短く書けます。色のコード(#FF0000)やメモリの番地で使います。たとえば FF は 15×16+15=255 で、8ビットがすべて1の状態です。
データ容量を見積もるとき、どこまで細かく計算すべきですか?
目的は、桁(MBか、GBか、TBか)を知ることです。行数×1行のバイト数で十分な場合が多いです。ただし、費用や性能の判断に使うときは、索引・バックアップ・複製・圧縮の影響を別に見積もり、実測で確認します。
整数の型を小さくすれば、メモリは必ず節約できますか?
データが大きい場合は、節約できます。たとえば100万行の列を64ビットから32ビットにすると、その列は半分になります。ただし、範囲を超えると、あふれて誤った値になります。変更の前に、最小値・最大値を確認します。
お金の計算に小数(float)を使ってはいけませんか?
誤差が許されない計算では、円単位の整数、または10進数を正確に扱う型を使うのが一般的です。分析で、おおまかな金額の平均を見るだけなら float でも問題になりにくいですが、合計が帳簿と1円でも合わなければならない場面では使わないでください。
文字数とバイト数が違うのは、なぜ問題になるのですか?
データベースの列の長さを「バイト」で制限していると、日本語は1文字が複数バイトなので、文字数が想定より少なくなって入り切らないことがあります。仕様に「文字数」か「バイト数」かを書き、日本語の例で検査してください。
確認問題
問1 5ビットで表せる値の数(通り数)はいくつか。
- ① 10通り
- ② 25通り
- ③ 32通り
- ④ 64通り
解答と解説
正解:③
1ビット増えるごとに2倍になるので、$2^5 = 32$ 通りです。
問2 1バイト(8ビット)の符号なし整数が表せる最大値はいくつか。
- ① 128
- ② 255
- ③ 256
- ④ 8
解答と解説
正解:②
256通りを0から数えるので、0〜255です。最大値は256ではなく255です。
問3 2進数の 1101 を10進数に直すと、いくつか。
- ① 13
- ② 11
- ③ 12
- ④ 15
解答と解説
正解:①
8+4+0+1=13 です。左から順に重みは8、4、2、1です。
問4 1行200バイトのデータが5,000,000行ある。1GB=10⁹バイトとして、容量の見積もりに近いのはどれか。
- ① 約100MB
- ② 約200MB
- ③ 約10GB
- ④ 約1GB
解答と解説
正解:④
200×5,000,000=1,000,000,000 バイトで、1GB(1,000倍系)です。
問5 「1GiBは何バイトか」を、1GBと取り違えて計算すると、どのような誤りが起こるか。
- ① 誤差は出ない。2つは同じ
- ② 約7%の差が出て、容量の見積もりがずれる
- ③ ちょうど2倍の差が出る
- ④ 1GiBのほうが小さい
解答と解説
正解:②
1GiB=1,073,741,824バイト、1GB=1,000,000,000バイトで、約7.4%の差があります。
問6 Pythonで 0.1 + 0.2 == 0.3 の結果が False になる理由として、最も適切なのはどれか。
- ① Python のバグだから
- ② 小数点以下を切り捨てるから
- ③ 0.1が2進数で正確に表せず、保存値が近似値だから
- ④ 変数に代入していないから
解答と解説
正解:③
0.1は2進数で無限小数になるため、有限のビットで近似して保存され、足し算に微小な誤差が残ります。
次に学ぶこと
次は 計算量と小さい反例 で、手順の「費用」の増え方(計算量)と、小さい反例で誤りを見つける方法を学びます。この授業の容量の見積もりも、全件を読む費用の見積もりの前提です。
型と数値の扱いは 数値・文字列・真偽値・演算子と型変換、単位と桁は 単位と桁と丸め に戻って確認できます。この授業の確認問題だけでモジュールの習得とはしません。ON06 の総合テストと、会員割引の条件を表で検証する自力課題で判定します。
キャリア学習:データサイエンティスト・機械学習エンジニア・DX推進・研究者を目指す人の学習アプリ。164モジュール・984授業を、ブラウザで動くSQLとPythonの演習で。基礎と各分野の最初のモジュールは無料。全部は2,980円の買い切り。
アプリを無料で開く有料版と無料版の違い