基本情報技術者試験 科目B サンプル問題 問16の解説|Unicode の符号位置を UTF-8 に変換する

基本情報技術者試験

科目B サンプル問題 問16難易度 ★★★★擬似言語・2進数・商と余り・for(減らす)最終更新 2026-09-22

プログラムは8行で、3周まわれば終わります。難しいのは1か所だけ ── 2進数の右から6桁を切り取るには、何で割ればよいかです。そこが分かれば、空欄は決まります。

難易度 ★★★★(当サイトの目安)── 符号化の規則を読み解いたうえで、6ビットずつ区切る(64で割る)と気づく必要がある。4段階の決め方は科目B 最短合格の戦略にあります。

出題

読み慣れない言葉があっても大丈夫です。次の節にまとめてあります。

出典:基本情報技術者試験 科目B サンプル問題 問16

次のプログラム中の    に入れる正しい答えを,解答群の中から選べ。二つの    には,同じ答えが入る。ここで,配列の要素番号は1 から始まる。

Unicode の符号位置を,UTF-8 の符号に変換するプログラムである。本問で数値の後ろに“(16)”と記載した場合は,その数値が16 進数であることを表す。

Unicode の各文字には,符号位置と呼ばれる整数値が与えられている。UTF-8 は,Unicode の文字を符号化する方式の一つであり,符号位置が800(16) 以上FFFF(16) 以下の文字は,次のように3 バイトの値に符号化する。

3 バイトの長さのビットパターンを 1110xxxx 10xxxxxx 10xxxxxx とする。ビットパターンの下線の付いた“x”の箇所に,符号位置を2 進数で表した値を右詰めで格納し,余った“x”の箇所に,0 を格納する。この3 バイトの値がUTF-8 の符号である。

例えば,ひらがなの“あ”の符号位置である3042(16) を2 進数で表すと 11000001000010 である。これを,上に示したビットパターンの“x”の箇所に右詰めで格納すると,1110xx11 10000001 10000010 となる。余った二つの“x”の箇所に0 を格納すると,“あ”のUTF-8 の符号 11100011 10000001 10000010 が得られる。

関数encode は,引数で渡されたUnicode の符号位置をUTF-8 の符号に変換し,先頭から順に1 バイトずつ要素に格納した整数型の配列を返す。encode には,引数として,800(16) 以上FFFF(16) 以下の整数値だけが渡されるものとする。

〔プログラム〕

○整数型の配列: encode(整数型: codePoint)
  /​* utf8Bytesの初期値は,ビットパターンの“x”を全て0に置き換え,
     8桁ごとに区切って,それぞれを2進数とみなしたときの値 *​/
  整数型の配列: utf8Bytes ← {224, 128, 128}
  整数型: cp ← codePoint
  整数型: i
  for (i を utf8Bytesの要素数 から 1 まで 1 ずつ減らす)
    utf8Bytes[i] ← utf8Bytes[i] + (cp ÷    の余り)
    cp ← cp ÷    の商
  endfor
  return utf8Bytes

解答群

ア ((4 - i) × 2) / イ (2 の (4 - i)乗) / ウ (2 の i 乗)

エ (i × 2) / オ 2 / カ 6

キ 16 / ク 64 / ケ 256

※ 解答群は原本では3列に並んでいます(字句は変えていません)。

答えだけ先に見る

正解は ク(64)です。

この問題に出てくる言葉

言葉と記号 ── 読み方の早見表をひらく
書き方 この問題では
符号位置 3042(16) 文字ごとに決まっている整数。「あ」は 3042(16)。(16) は16進数の印です
ビットパターン 右詰め 0 と 1 を並べた型。右詰めは、右端をそろえて入れること。左に余った x には 0 を入れます
… の余り … の商 整数どうしの割り算の余りと商。7 ÷ 3 は 2 余り 1 なので、余りは 1、商は 2
{224, 128, 128} 3つの整数が入った配列。utf8Bytes[1] が 224、utf8Bytes[3] が 128 です
for (i を utf8Bytesの要素数 から 1 まで 1 ずつ減らす) i を 3, 2, 1 の順に変えながら endfor までをくり返す。後ろの要素から処理します
/​* … *​/ 注釈。読む人への説明で、実行には関係ありません

x に入るのは、右から6桁ずつ

まず、問題文の「あ」の例を見直します。符号位置 3042(16) の2進数 11000001000010 を、右から6桁ずつ区切ると、x の並びとぴったり重なります。

「あ」の2進数を、右から6桁ずつ x に入れる

琥珀の数字= 符号位置の2進数。上下で同じ桁にそろえてあります

出題の例(3042(16) = 11000001000010)

ビットパターン

1110xxxx 10xxxxxx 10xxxxxx

右から6桁ずつ
区切った2進数

      11   000001   000010

x に入れると

11100011 10000001 10000010

いちばん左に残った 11 は2桁しかないので、1バイト目の x の残り2つには 0 が入ります。

2バイト目と3バイト目の x は6個ずつ。だから符号位置の2進数は、右から6桁ずつ区切って、後ろのバイトから入れていけばよい。プログラムの for も i を 3, 2, 1 と後ろから動かしています。

空欄のある for の中身は2行です。

〔プログラム〕空欄のある for

  for (i を utf8Bytesの要素数 から 1 まで 1 ずつ減らす)
    utf8Bytes[i] ← utf8Bytes[i] + (cp ÷    の余り)
    cp ← cp ÷    の商
  endfor

※ 上の〔プログラム〕からの抜粋です(1字も変えていません)。

入れ方は足し算です。utf8Bytes の初期値 {224, 128, 128} は、注釈のとおり x を全部 0 にした 11100000 10000000 10000000。x の場所が 0 なので、6桁の値を足せば、そのまま x の場所に入ります。足すのは6桁に収まる値なので、x の外へ繰り上がることはありません(128 + 2 = 130 は 10000000 + 000010 = 10000010)。

つまり1行目で cp の右から6桁を utf8Bytes[i] に足し、2行目で その6桁を cp から取り除く。次の周では、取り除いたあとの右から6桁が、1つ前のバイトに入ります。

右から6桁を切り取る計算を決める

10進数で考えると分かりやすくなります。5678 の右から2桁を取り出すには 100 で割ります。5678 ÷ 100 は 56 余り 78 ── 余りが右2桁、商が残りの左側です。100 は 10 を2回かけた数。10進数は1桁左へ行くごとに 10 倍になるからです。

2進数は1桁左へ行くごとに 2 倍です。だから2進数の右から6桁を取り出すには、2 を6回かけた 64 で割る。余りが右6桁、商が残りの左側です。空欄は2つとも 64 です。

「あ」の符号位置 3042(16) は、10進数に直すと 3 × 4096 + 4 × 16 + 2 = 12354 です。これを encode に通して確かめます。

「あ」(12354)を encode に通す

琥珀の数字= この周で切り取る右6桁(3周目は残りが2桁だけ)と、それが入った場所。2進数は右端をそろえてあります

1周目 i = 3

周の始めの cp

12354 = 11000001000010    

cp ÷ 64 の余り

    2 =         000010    

utf8Bytes[3]

128 + 2 = 130 = 10000010

cp ÷ 64 の商
(次の cp)

  193 = 11000001          

2周目 i = 2

周の始めの cp

  193 =       11000001    

cp ÷ 64 の余り

    1 =         000001    

utf8Bytes[2]

128 + 1 = 129 = 10000001

cp ÷ 64 の商
(次の cp)

    3 =       11          

3周目 i = 1

周の始めの cp

    3 =             11    

cp ÷ 64 の余り

    3 =             11    

utf8Bytes[1]

224 + 3 = 227 = 11100011

cp ÷ 64 の商
(次の cp)

    0 = (残りなし)      

3周で utf8Bytes = {227, 129, 130} = 11100011 10000001 10000010。問題文にある「あ」の UTF-8 と同じです。

解答群を見る

空欄は 64 ── ク です。

答え合わせ

ク 64

ほかの数で割ると、切り取る桁数がずれます。2 は1桁、16 は4桁、256 は8桁を切り取る数で、どれも x の6個と合いません。6 は桁数そのもので、「6桁」と「6 で割る」の取り違えです。i を使う式(ア〜エ)は周ごとに割る数が変わります。たとえばアは1周目(i = 3)に 2 で割るので、1桁しか切り取れません。2バイト目と3バイト目はどちらも6桁なので、割る数は周ごとに変わってはいけません。

1バイト目の x は4個しかないのに 64 でよいのは、符号位置が FFFF(16) 以下=2進数で16桁以下だからです。6桁を2回取ると、残りは4桁以下しかありません。3周目の余りはその残り全部で、4個の x に収まります。

次に読む

この問題でどこに手間取ったかで、行き先が変わります。

この記事で引用した資料

いずれも独立行政法人情報処理推進機構(IPA)が公表したものです。IPAは公表済みの試験問題について、教育目的での使用に許諾および使用料を不要としていますが、著作権は放棄していません。本記事では問題文を改変せずに引用しています。

Copied title and URL