基本情報技術者試験のサンプル問題(科目B)を解いてみよう。
今回のテーマは、「五数要約」である。

〔プログラム〕
○実数型: findRank(実数型の配列: sortedData, 実数型: p)
整数型: i
i ← (p × (sortedDataの要素数 - 1)) の小数点以下を切り上げた値
return sortedData[i + 1]
○実数型の配列: summarize(実数型の配列: sortedData)
実数型の配列: rankData ← {} /* 要素数0の配列 */
実数型の配列: p ← {0, 0.25, 0.5, 0.75, 1}
整数型: i
for (i を 1 から pの要素数 まで 1 ずつ増やす)
rankDataの末尾 に findRank(sortedData, p[i])の戻り値 を追加する
endfor
return rankData
解答群
ア {0.1, 0.3, 0.5, 0.7, 1}
イ {0.1, 0.3, 0.5, 0.8, 1}
ウ {0.1, 0.3, 0.6, 0.7, 1}
エ {0.1, 0.3, 0.6, 0.8, 1}
オ {0.1, 0.4, 0.5, 0.7, 1}
カ {0.1, 0.4, 0.5, 0.8, 1}
キ {0.1, 0.4, 0.6, 0.7, 1}
ク {0.1, 0.4, 0.6, 0.8, 1}
正解:ク
この問題は、昇順に並んだデータに対して、特定の「五数要約(minimum, Q1, median, Q3, maximum)」を求める関数 summarize
の動作を理解することが問われている。
まずは「要点」を整理しよう
関数 summarize({0.1, 0.2, ..., 1.0})
を呼び出すと、以下の5つのパーセンタイルに対応する値を返す仕組みになっている。
※パーセンタイルとは?
パーセンタイルとは、データを小さい順に並べたときに、全体の何%の位置にあるかを示す指標。
p = {0, 0.25, 0.5, 0.75, 1}
なお、それぞれの意味は以下の通りである。
p値 | 意味 |
---|---|
0 | 最小値 (min) |
0.25 | 第1四分位数 (Q1) |
0.5 | 中央値 (median) |
0.75 | 第3四分位数 (Q3) |
1 | 最大値 (max) |
findRank 関数の動作
i ← ceil(p × (要素数 - 1))
return sortedData[i + 1]
与えられた p
に対して、次のようにインデックスを求めて、配列からその値を返している。
配列 sortedData
は次の 10 要素である。
{0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0}
1 2 3 4 5 6 7 8 9 10 ← 添字(1から開始)
ここで、sortedData
の要素数を「N」とする。
たとえば要素が10個あるとき、隣り合う要素の間にある区間は9個になる。
この「区間の位置」を基準にしてパーセンタイルの位置を計算するために、N - 1
を使う。
つまり、要素数 N = 10 ならば N - 1 = 9
となり、パーセンタイルの位置は p × 9
で求められる。
このとき、計算された位置が小数(例:2.25)の場合は、実際の配列のインデックスに対応させるために 切り上げ(ceil()
) を使い、最も近い上側の整数位置を選ぶ。
設問の「i ← (p × (sortedDataの要素数 - 1)) の小数点以下を切り上げた値
」のうち、「小数点以下を切り上げた値」は、この ceil()
を日本語で表現していると読み取れる。
本解説でも ceil()
を使用して説明する。
※ceil 関数は、与えられた浮動小数点数を切り上げて、最も近い整数を返す関数である。
C言語やC++で使用する場合は、<math.h> ヘッダーをインクルードする必要がある。
また、配列のインデックスは1から始まるため、最終的に参照するのは i + 1
番目の要素になる。
それぞれの p
に対して何が返るかを計算してみよう。
各 p に対して findRank の計算をしよう
① p = 0
i = ceil(0 × 9) = ceil(0) = 0
return sortedData[0 + 1] = sortedData[1] = 0.1
② p = 0.25
i = ceil(0.25 × 9) = ceil(2.25) = 3
return sortedData[3 + 1] = sortedData[4] = 0.4
③ p = 0.5
i = ceil(0.5 × 9) = ceil(4.5) = 5
return sortedData[5 + 1] = sortedData[6] = 0.6
④ p = 0.75
i = ceil(0.75 × 9) = ceil(6.75) = 7
return sortedData[7 + 1] = sortedData[8] = 0.8
⑤ p = 1
i = ceil(1 × 9) = ceil(9) = 9
return sortedData[9 + 1] = sortedData[10] = 1.0
戻り値 rankDataを確認しよう
{0.1, 0.4, 0.6, 0.8, 1}
選択肢の中では、
ク {0.1, 0.4, 0.6, 0.8, 1} であり、
正解となる。
まとめ
- 五数要約は、 Min(最小),Q1, median, Q3, Max(最大)の5つの代表値のこと。
- 本問は五数要約をパーセンタイルに基づいて抽出する処理である。
- p = {0, 0.25, 0.5, 0.75, 1} に対応する値を出力することで、五数要約をプログラム的に理解していることが求められる。
C言語のコードで本問を確認してみよう!
#include <stdio.h>
#define SIZE 10
// 手動で ceil を再現する関数(整数切り上げ)
int manualCeil(double value) {
int intPart = (int)value;
if (value > (double)intPart) {
return intPart + 1;
} else {
return intPart;
}
}
// findRank関数:pに対応する値を返す
double findRank(double sortedData[], int size, double p) {
double position = p * (size - 1);
int i = manualCeil(position);
return sortedData[i];
}
// summarize関数:五数要約を求める
void summarize(double sortedData[], int size, double rankData[]) {
double p[] = {0.0, 0.25, 0.5, 0.75, 1.0};
for (int i = 0; i < 5; i++) {
rankData[i] = findRank(sortedData, size, p[i]);
}
}
int main() {
double sortedData[SIZE] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0};
double rankData[5];
summarize(sortedData, SIZE, rankData);
printf("五数要約: {");
for (int i = 0; i < 5; i++) {
printf("%.1f", rankData[i]);
if (i < 4) printf(", ");
}
printf("}\n");
return 0;
}
実行結果
五数要約: {0.1, 0.4, 0.6, 0.8, 1.0}
manualCeil() 関数は、ceil() の代わりに小数点以下を判定して切り上げる処理をしている。
<math.h>を使わないことで、幅広い環境で動作する。
コメント