IPv4 アドレスを 32bit 整数に変換

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

IPv4 アドレスを 32bit 整数に変換

このレッスンで分かること

  • 192.168.1.1 のような表記の IPv4 アドレスを、内部的には 1 つの 32bit 整数 として扱うとさまざまな処理が一瞬で書けるようになります
  • IPv4 アドレスは 4 つのオクテット (8bit × 4 = 32bit) で構成されています
  • 4 つのオクテット a.b.c.d を 32bit 整数にするには、それぞれを 8bit ずつ位置をずらして足し合わせます

IPv4 アドレスを 32bit 整数に変換 とは

192.168.1.1 のような IPv4 アドレスを 32bit の整数に変換する関数を作ります。本レッスンでは、IPv4 アドレスを 32bit 整数に変換 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

192.168.1.1 のような表記の IPv4 アドレスを、内部的には 1 つの 32bit 整数 として扱うとさまざまな処理が一瞬で書けるようになります。本レッスンでは、ドット区切り表記 (dotted quad) を整数に変換する関数を実装します。

なぜ整数に変換するのか

IPv4 アドレスは 4 つのオクテット (8bit × 4 = 32bit) で構成されています。文字列のまま比較しようとすると辞書順比較になり、9.0.0.010.0.0.0 の大小判定で誤った結果が出ます ("9" > "10" になる)。整数化すれば次のメリットがあります。

  • 比較や大小判定が O(1) で正しく行える
  • CIDR (192.168.1.0/24) との一致判定が bit AND 1 回でできる
  • データベースに 1 カラム (UNSIGNED INT) で格納でき、インデックスも効く
  • ルーティングテーブルでの 最長一致 も整数演算で簡単

ネットワーク機器の内部では IPv4 を uint32 で扱うのが普通です。文字列表現は人間向けのインターフェースに過ぎません。

計算の考え方

4 つのオクテット a.b.c.d を 32bit 整数にするには、それぞれを 8bit ずつ位置をずらして足し合わせます。式は次の通りです。

result = (a << 24) | (b << 16) | (c << 8) | d

つまり a が最上位 8bit、d が最下位 8bit です。192.168.1.1 を計算してみます。

  • 192 << 24 = 3221225472
  • 168 << 16 = 11010048
  • 1 << 8 = 256
  • 1 = 1
  • 合計 = 3232235777
diagram (will load when visible)

図のポイント (テキスト併記)

  • << はビット左シフトで、x << 8x * 256 と同じです

<< はビット左シフトで、x << 8x * 256 と同じです。| は OR で、ここでは + でも結果は同じです (オクテット同士は重ならないため)。

Python 実装

Python

def ipToInt(ip): parts = ip.split('.') a, b, c, d = (int(p) for p in parts) return (a << 24) | (b << 16) | (c << 8) | d

split でドットを区切ってリスト化し、それぞれを整数に変換します。続いてビット演算で 32bit に詰めます。Python の整数は任意精度なので 3221225472 のような大きな値もそのまま扱えます。

JavaScript 実装

JavaScript

function ipToInt(ip) { const parts = ip.split('.').map(Number); return parts[0] * 16777216 + parts[1] * 65536 + parts[2] * 256 + parts[3]; }

JavaScript のビット演算は 32bit 符号付き なので、192.168.1.1 のように最上位ビットが立つ値だと << を使うと負の数になります。これを避けるため * 16777216 のように 掛け算で書く のが定石です。167772162^24655362^162562^8 です。

JavaScript で (192 << 24) を試すと -1073741824 になります。符号付きビット演算の罠です。>>> 0 で符号なしに戻すこともできますが、掛け算のほうが安全です。

入力の前提と検証

本問題では ip正しい形式の IPv4 であると仮定します (a.b.c.d、各オクテットは 0 〜 255 の整数)。実務では inet_aton / inet_pton のような標準ライブラリを使うのが安全です。Python なら import ipaddress; int(ipaddress.IPv4Address(ip)) が一番堅牢な書き方です。

具体例

  • "0.0.0.0"0
  • "127.0.0.1"2130706433
  • "192.168.1.1"3232235777
  • "255.255.255.255"4294967295 (32bit の最大値)
  • "10.0.0.1"167772161

255.255.255.255 の整数表現 42949672952^32 - 1 で、これより大きい値は IPv4 では表現できません。

よくある間違い

  • ドットで split した結果を文字列のまま掛け算してしまう ('192' * 256 のようなバグ)
  • JavaScript で << を使い、最上位ビットが立つ値で負の数になる
  • 並び順を間違えて (d << 24) | ... のように逆順に詰めてしまう
  • IPv6 (::1) を渡されることを想定せず、split('.') で 4 個未満になっても気付かない
  • オクテットの上限 255 を超えるバリデーションを怠る

やってみよう

関数 ipToInt(ip) を実装してください。引数 ip はドット区切りの IPv4 文字列 (例: "192.168.1.1") で、対応する 32bit 整数 (0 以上) を返します。

よくある質問

Q. IPv4 と IPv6 はどう違いますか?

A. IPv4 は 32 ビット(約 43 億個)、IPv6 は 128 ビット(事実上無限)のアドレス空間です。IPv4 アドレス枯渇問題への解として IPv6 が登場し、両者は併存しています(デュアルスタック)。サーバー設計では両方に対応するのが現代的です。

Q. プライベート IP とグローバル IP の違いは?

A. プライベート IP(192.168.x.x、10.x.x.x、172.16-31.x.x)は組織内だけで有効、グローバル IP はインターネット上で一意です。家庭の機器はプライベート IP を持ち、NAT でグローバル IP に変換されて外と通信します。

Q. IP アドレスからユーザーを特定できますか?

A. 完全な特定はできません。IP は接続元のおおよその地域とプロバイダを示すだけで、複数ユーザーで共有されることも多いです。ログ調査では IP + ユーザーエージェント + Cookie などを組み合わせて識別します。プライバシー保護の観点でも単一情報では追跡できません。

次のレッスン

次は 32bit 整数を IPv4 アドレスに変換 に進みましょう。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. IPv4 → 整数 の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. IPv4 → 整数 とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

要件

  1. ドット区切りの IPv4 文字列を 32bit 整数に変換する
  2. オクテットの順序は (a << 24) | (b << 16) | (c << 8) | d とする
  3. 255.255.255.255 が 4294967295 になるよう、符号なしの値として扱う

入出力例

test-cases.txt

ipToInt("0.0.0.0")0 ipToInt("127.0.0.1")2130706433 ipToInt("192.168.1.1")3232235777 ipToInt("255.255.255.255")4294967295 ipToInt("10.0.0.1")167772161 ipToInt("172.16.0.1")2886729729 ipToInt("8.8.8.8")134744072

ヒント

main.py
main.py
学習モード

メモ

IPv4 アドレスを 32bit 整数に変換

⌘S で保存