1. A (U+0041)
  2. DEL (U+007F)
  3. U+0080 境界
  4. é (U+00E9)
  5. U+07FF 境界
  6. U+0800 境界
  7. あ (U+3042)
  8. U+FFFF 境界
  9. U+10000 境界
  10. snake emoji 🐍 (U+1F40D)
コース一覧
コンピューターサイエンス入門:理論編
UTF-8 のバイト長を返す

コンピューターサイエンス入門:理論編

2 進数、論理演算、ビット演算、データ構造、計算量、メモリモデルなど、プログラミングの土台となるコンピュータサイエンスの理論知識を学べるコースです。プログラミングを始めたばかりの学習者や、CS の体系的な土台を作りたい現役エンジニアを対象としています。約 13 時間 (1 日 30 分 × 26 日) で 53 レッスンを修了でき、修了後はコードのパフォーマンスや設計判断の根拠を理解した上で実装できるようになります。

1
2進数とビット演算
01. 2進数から10進数への変換5分
02. 10進数から2進数への変換5分
03. ビットAND演算でフラグ判定5分
04. OR / XOR でフラグを操作する5分
05. popcount で 1 のビット数を数える5分
06. シフト演算で 2 倍 / 半分5分
07. 16 進数から 10 進数への変換5分
08. 第 1 章まとめクイズ5分
2
文字コードと真偽値ロジック
01. 文字 → ASCII コード5分
02. コード → 文字5分
03. UTF-8 のバイト長を返す5分
04. AND / OR の真理値表5分
05. NOT / XOR の真理値表5分
06. 含意 (→) を AND/OR/NOT で表現5分
07. ド・モルガンの法則5分
08. 第2章まとめクイズ5分
3
計算量とBig-O
01. forループの実行回数を返す5分
02. 入れ子ループの実行回数5分
03. 線形探索 (O(n))5分
04. 二分探索 (O(log n))5分
05. バブルソート5分
06. 配列の最大と最小5分
07. 累積和で範囲合計5分
08. 第3章まとめクイズ5分
4
データ構造 (基本)
01. スタック (push/pop) を実装する5分
02. キュー (enqueue / dequeue) を実装する5分
03. カッコのバランス判定 (スタック応用)5分
04. set で重複を除去する5分
05. map で出現回数を数える5分
06. 二数の和 (map で O(n))5分
07. アナグラム判定5分
08. 第 4 章クイズ — データ構造 (基本)5分
5
ファイル / メモリ / IO 概念
01. バイト → KB 変換5分
02. ディスクサイズフォーマット5分
03. キャッシュヒット率5分
04. LRU 簡易シミュレーション5分
05. エンディアンの入れ替え (uint32)5分
06. バッファ範囲チェック5分
07. 第5章まとめクイズ5分
6
ネットワークと符号化
01. Base64 エンコード後の長さ計算5分
02. URL エンコード対象文字数5分
03. IPv4 アドレスを 32bit 整数に変換5分
04. 32bit 整数を IPv4 アドレスに変換5分
05. CIDR プレフィックスからネットマスクを作る5分
06. 単純チェックサム5分
07. 第6章まとめクイズ5分
7
設計と DB 基礎
01. 重複データを 1NF に変換 (フラットなリスト化)5分
02. キーで join (map 利用)5分
03. 残高転送のトランザクション風処理5分
04. CAP の availability 模擬5分
05. URL ルーティング5分
06. 疎結合と密結合 — 依存性注入で設計を変える12分
07. コース総まとめクイズ5分

UTF-8 のバイト長を返す

文字コードと文字化け

「1 文字 1 バイト」で見積もると、足りなくなる

入力欄を 100 文字までにしたい。保存先を 100 バイトで用意したら、日本語で 40 文字ほど入れた時点で溢れました。英語でテストしていたときは、何ともなかったのにです。

原因は単純で、UTF-8 では 1 文字の大きさが一定ではないからです。A は 1 バイトですが、あ は 3 バイトを使います。文字数とバイト数は別の数え方で、掛け算では行き来できません。

Python

print(len('あA')) # 2 文字数 print(len('あA'.encode('utf-8'))) # 4 バイト数

先頭のバイトが、続きが何個あるかを宣言している

長さが一定でないなら、どこで 1 文字が終わるのか分からなくなりそうです。UTF-8 はそこを、先頭バイトの上位のビットで解決しています。

プレーンテキスト

0xxxxxxx 1 バイト 110xxxxx 10xxxxxx 2 バイト 1110xxxx 10xxxxxx 10xxxxxx 3 バイト 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 4 バイト

先頭が 0 なら 1 バイトで終わり、110 なら続きが 1 つ、1110 なら続きが 2 つ、という約束です。続きのバイトは必ず 10 で始まるので、途中から読み始めても文字の切れ目を見つけ直せます。

先頭が 0 の形は ASCII とまったく同じ並びです。だから英数字だけのファイルは、UTF-8 として読んでも 1 バイトも変わりません。

日本語が 3 バイトになるのは、11 ビットに入らないから

上の並びで、x の数を数えてください。これが文字の番号に使える本体のビット数です。1 バイト形式は 7 個、2 バイト形式は 5 個と 6 個で 11 個、3 バイト形式は 4 個と 6 個と 6 個で 16 個になります。

あ の番号は 0x3042 で、2 進数にすると 14 桁あります。11 桁には入りません。だから 2 バイト形式では表しきれず、16 桁まで置ける 3 バイト形式に回されます。日本語の大半がこの範囲に並んでいるので、まとめて 3 バイトになります。

つまりバイト数は、文字の種類ではなく番号の大きさだけで決まります。何ビットあれば足りるか、を考えれば、境目の値は自分で組み立て直せます。

数え方を混ぜると、途中で切れる

文字化けの多くは、バイト数で長さを切ったときに起きます。3 バイトの真ん中で切ると、先頭バイトだけが残った半端な並びができます。読む側は続きを待っているのに来ないので、置換文字に化けます。

長さを測るとき、切り出すとき、保存するときで、文字数とバイト数のどちらで数えているのかを毎回はっきりさせてください。データベースの列の長さ制限も、文字数で指定するものとバイト数で指定するものが混在しています。

要件

  1. 3 つの境界 (0x80, 0x800, 0x10000) で判定する
  2. 1〜4 の整数を返す
  3. 範囲外の入力は考慮しなくてよい

入出力例

utf8Len(65) → 1 utf8Len(127) → 1 utf8Len(128) → 2 utf8Len(233) → 2 utf8Len(2047) → 2 utf8Len(2048) → 3 utf8Len(12354) → 3 utf8Len(65535) → 3 utf8Len(65536) → 4 utf8Len(128013) → 4

ヒント

if/elif で順番に境界を判定すると素直に書けます

10 進ではなく 16 進 (0x80 など) で書くと境界が読みやすい

境界は < で比較 (<= だと境界値の扱いが逆になります)

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/05/19·更新 2026/08/26

関連レッスン

  • AND / OR の真理値表

    2 つの真偽値 (0/1) を受け取り、AND と OR の結果を 2 ビットに詰めた整数で返す関数を実装します。論理演算の基礎を手で動かして確認します。

  • NOT / XOR の真理値表

    2 つの真偽値 (0/1) を受け取り、NOT a と a XOR b の結果を 2 ビットに詰めた整数で返す関数を実装します。

  • 含意 (→) を AND/OR/NOT で表現

    論理学の含意 a → b を AND/OR/NOT の組み合わせで実装し、0/1 で返す関数を作ります。「a ならば b」の真偽の不思議さも体感します。

  • ド・モルガンの法則

    ド・モルガンの法則を使って NOT (a AND b) を NOT a OR NOT b に変換する関数を実装し、等価性を実感します。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • テストバグを見つける工程
  • ビット2進数の1桁。0 か 1 のどちらか
  • 文字化け送受信側のエンコード不一致による表示崩れ
  • データベースデータを構造化して保存する仕組み
main.py
学習モード
エディタを読み込んでいます

メモ

UTF-8 のバイト長を返す

⌘S で保存