【確率シミュレータ】基本情報技術者試験 ランダムマークの合格率計算

🍀概要

 情報処理技術者試験 基本情報技術者は、IT企業の新人の登竜門としての資格試験として広く浸透しています。科目A・科目Bとして、連続して試験が実施されます。本試験では、どちらも、総合評価点600点以上の合格基準があります。しかし、もし一切知識がない状態でランダムにマークした場合、どれほどの確率で合格できるのでしょうか
 基本情報技術者試験はIRT(項目応答理論)に基づいて採点されますが、このシミュレーターでは便宜的に「各科目100点満点中60点相当で合格」を基準とした素点計算を行います。本記事では、この疑問に答えるため、モンテカルロシミュレーションを用いた確率シミュレーターを作成し、その詳細な結果とプログラムコードを公開します。
※本記事の執筆者は、中学校・高等学校教諭一種免許状(数学)を保有しており、数学的な観点から試験制度を分析しています。

🧾出題形式の基本

基本情報技術者試験は、以下の形式で出題されます。本シミュレーターでは素点計算とするため、以下の条件でシミュレーションを行います。

出典: 情報処理推進機構 基本情報技術者試験 総問題数: 80問 (科目A: 60問, 科目B: 20問)

  • 科目A: 60問 / 4択問題
  • 科目B: 20問 / 下記「 配点設定」の表のとおりの選択肢数

各科目の配点: 科目A、科目Bそれぞれ100点満点とみなしてシミュレートします。詳細は下記「配点設定」を参照してください。

各問題のランダム正答率: その問題の「選択肢の数」列の値の逆数(例: 4択なら1/4、8択なら1/8、10択なら1/10)。

合格基準: 科目A、科目Bそれぞれで合計得点率60%以上(100点満点中60点以上)で合格と判定します。両方の科目が合格基準を満たすことで、総合合格とみなします。


配点設定

本シミュレーターでは、以下の配点として計算します。

  • 科目A: No.1~60。1問あたり1点とする。(科目Aの満点: 60問×1点/問=60 点)
    • 合格に必要な素点: 60点 (素点満点)×60%=36 点以上
  • 科目B: No.61~80 (元のNo.1~20)。1問あたり1点とする。
    • 合格に必要な素点: 20問×1点/問×60%=12 点以上

各問題の完全ランダム正答率: その問題の「選択肢の数」列の値の逆数(例: 4択なら1/4、8択なら1/8、10択なら1/10)。

出典:基本情報技術者試験 サンプル問題セットを分析し、選択肢の数を準拠。🔗取り扱いガイドライン

※科目B

No (科目B内のNo)全体No (科目A+B)選択肢の数配点 (各科目の素点換算)
16161
26251
36371
46441
56571
66641
76761
86841
96941
107061
117141
127241
137341
147481
157541
167691
1777101
1878101
197951
208071

📊 IRT(項目応答理論)と素点計算の違い:本シミュレーターの立ち位置

基本情報技術者試験の採点方式はIRT(項目応答理論)が採用されています。これは、一般的な試験で用いられる素点計算(正解した問題数に応じた単純な点数計算)とは異なる、統計的な採点方式です。

IRTとは?

IRTでは、個々の問題に「難易度」や「識別力(受験者の能力をどれだけ正確に区別できるか)」といったパラメータが設定されており、受験者の解答パターン(どの問題を正解し、どの問題を間違えたか)に基づいて、その受験者の潜在的な能力(評価点)を算出します。 このため、IRT採点では以下のような特徴があります。

  • 問題ごとの点数が一律ではない: 難しい問題を正解すれば高得点に繋がりやすく、簡単な問題を間違えれば減点幅が大きくなることがあります。
  • 同じ正答数でも点数が異なる可能性がある: 正解した問題の組み合わせによって、最終的な評価点が変わることがあります。
  • 受験者間の公平性の確保: 試験回によって問題の難易度が変動しても、受験者間の能力評価の公平性が保たれやすいという利点があります。

本シミュレーターにおける素点計算の採用理由

IRTは非常に精密な採点方式ですが、その具体的なロジック(各問題のパラメータなど)は公開されていません。そのため、外部からIRT採点結果を正確に再現することは極めて困難です。

そこで、本シミュレーターでは、すべての採点対象問題の配点が均等であると仮定した「素点計算」を採用しています。これは、実際のIRT採点とは異なるものの、以下の点で確率シミュレーションの近似値として有効であると考えます。

  • 計算の簡潔性: 未公開の複雑なIRTロジックを用いることなく、正答数と合格基準の関係をシンプルに計算できます。
  • 傾向の把握: 完全な運任せや、特定の知識レベル・絞り込み能力を持つ場合の合格率の傾向を把握するには、素点計算でも十分な近似値を得られます。
  • 学習戦略の示唆: 各分野で必要な正答数を具体的に示すことで、受験者がどの分野に重点を置くべきか、どの程度「確実に得点できる問題」を増やすべきか、といった学習戦略を検討する上での現実的な示唆を提供できます。

したがって、本シミュレーターで算出される合格率は、実際の基本情報技術者試験におけるIRT採点の結果と完全に一致するものではありません。あくまで「もし素点計算であったならば」という仮定に基づいた近似的な合格確率として、ご自身の学習の目安としてご活用ください。

📘モンテカルロシミュレーションとは?:実践的な確率計算アプローチ

 基本情報技術者試験で上記の合格基準を全て満たす確率を、厳密に数学的に計算するのは非常に複雑です。そこで登場するのが「モンテカルロシミュレーション」です。
 これは、実際にランダムにマークシートを塗りつぶし、採点する試行を莫大な回数(例えば10万回)繰り返すことで、確率を近似的に求める手法です。
 例えば、たった1回試行しただけでは、偶然の偏りが大きく、その結果は信頼できません。しかし、これを10万回、100万回と繰り返すことで、試行回数中に「合格基準に達した回数」を数え、「合格回数 ÷ 総試行回数 × 100%」と計算すれば、非常に高い精度で合格確率を推定できます。
 まさに、この「サイコロを振るように何度も試行を重ねて、事象の発生確率を導き出す」のがモンテカルロシミュレーションの核心です。この考え方に基づいて、今回の確率計算を行います。

📗さらにリアルなシミュレーションを!:受験者の実力を加味した分析

 実際の受験者が全問の答えを全く知らない、ということは稀でしょう。そこで、より現実に即したシミュレーションを行うために、以下の2つのシナリオも追加で分析しました。

  1. 「確実に得点できる問題」がある場合: 事前に一定数の問題が解けると仮定し、それ以外の問題をランダムにマークした場合の合格率を算出。
  2. 「選択肢を絞り込める学力」がある場合: 4択問題に対し、解答の精度を高める学力(例えば、4択問題の場合誤りの選択肢を25%(1個)除外して「3択」に絞り込める、あるいは50%(2個)除外して「2択」にまで絞り込める)があるケースを想定し、それぞれの場合の合格率をシミュレーション。

 これらの詳細なシミュレーション結果から、あなたの学習戦略を考える上での新たな視点が見つかるかもしれません。

💻プログラム ※おまけ

プログラムに興味ある方向けの記載です。「科目B」の問題と思って読み解くと、面白いかもしれません。

📐ロジック設計書

合格判定ロジック

基本情報技術者試験 合格確率シミュレーションの最終ロジック

基本情報技術者試験の合格確率をモンテカルロシミュレーションで計算するためのロジックは、以下の手順で行います。本シミュレーターは、IRT(項目応答理論)ではなく、各問題の配点が定義された「素点計算」に基づきます。


1. 問題データとシミュレーション定数の定義

  • 科目Aの定数:
    • TOTAL_QUESTIONS_A: 60 (総問題数)
    • CHOICES_A: 4 (4択固定)
    • SCORE_PER_QUESTION_A: 1 (科目Aの各問題の配点、素点計算用)
    • REQUIRED_RAW_SCORE_A: 36 (合格に必要な科目Aの素点。 60×(60/100)=36点)
  • 科目Bの定数:
    • TOTAL_QUESTIONS_B: 20 (総問題数)
    • SCORE_PER_QUESTION_B: 1 (科目Bの各問題の配点、素点計算用)
    • REQUIRED_RAW_SCORE_B: 12 (合格に必要な科目Bの素点。科目Bの素点満点は20点なので、20点×(60/100)=12点)
    • 各問題の選択肢の定義(科目B): 科目Bの各問題の選択肢の数のみを保持するデータ構造(例: 配列やリスト)を用意します。配点は一律1点となります。具体的な科目Bの問題の選択肢数データ:科目B選択肢数リスト = [6, 5, 7, 4, 7, 4, 6, 4, 4, 6, 4, 4, 4, 8, 4, 9, 10, 10, 5, 7]
  • 共通シミュレーション定数:
    • TOTAL_EXAM_QUESTIONS: TOTAL_QUESTIONS_A + TOTAL_QUESTIONS_B (合計80問)
    • DEFAULT_TRIALS: 10000 (デフォルトの試行回数)

2. 1回の試行における問題の解答シミュレーション (simulateScenario メソッド内)

各モンテカルロ試行において、以下の手順で科目Aと科目Bの解答を個別にシミュレートします。

  • 入力パラメータ:
    • answerMethod (ランダム解答方式の定義)
    • knownCorrectQuestionsOverall (試験全体で事前に知っている問題の総数)
    • trials (試行回数)
  • 「事前に知っている問題」の割り振り:
    • knownCorrectQuestionsOverall を、科目Aと科目Bの総問題数の比率で按分します。
    • knownCorrectQuestionsA = (int) Math.round(knownCorrectQuestionsOverall * ((double) TOTAL_QUESTIONS_A / TOTAL_EXAM_QUESTIONS));
    • knownCorrectQuestionsB = knownCorrectQuestionsOverall - knownCorrectQuestionsA;
      • 注意点: knownCorrectQuestionsATOTAL_QUESTIONS_A を超えないように、また knownCorrectQuestionsBTOTAL_QUESTIONS_B を超えないように調整が必要です。ただし、knownCorrectQuestionsOverallTOTAL_EXAM_QUESTIONS を超えない範囲であれば、この計算で問題ありません。万が一のケースのために、Math.min()などで上限を設けることも検討できます。
  • 科目Aの解答シミュレーション:
    1. 「事前に知っている問題」の処理(科目A):
      • 0からTOTAL_QUESTIONS_A - 1までのインデックスを格納したリストを作成し、シャッフルします。
      • シャッフルされたリストの先頭からknownCorrectQuestionsA個のインデックスを選び、これらの問題を正解とマークし、対応する素点(SCORE_PER_QUESTION_A)を加算します。これらをknownCorrectIndicesAセットに格納します。
    2. 「残りの問題」の処理(ランダム解答、科目A):
      • 0からTOTAL_QUESTIONS_A - 1までの全てのインデックスを走査します。
      • knownCorrectIndicesAに含まれない問題について、answerMethod.isCorrect(random, CHOICES_A) を使用して正解かどうかを判定します(科目Aは常に4択)。
      • 正解であればSCORE_PER_QUESTION_Aを科目Aの合計点に加算します。
  • 科目Bの解答シミュレーション:
    1. 「事前に知っている問題」の処理(科目B):
      • 0からTOTAL_QUESTIONS_B - 1までのインデックスを格納したリストを作成し、シャッフルします。
      • シャッフルされたリストの先頭からknownCorrectQuestionsB個のインデックスを選び、これらの問題を正解とマークし、対応する素点(SCORE_PER_QUESTION_B)を加算します。これらをknownCorrectIndicesBセットに格納します。
    2. 「残りの問題」の処理(ランダム解答、科目B):
      • 0からTOTAL_QUESTIONS_B - 1までの全てのインデックスを走査します。
      • knownCorrectIndicesBに含まれない問題について、answerMethod.isCorrect(random, 科目B選択肢数リスト.get(j)) を使用して正解かどうかを判定します(科目Bは問題ごとに選択肢数が異なる)。
      • 正解であればSCORE_PER_QUESTION_Bを科目Bの合計点に加算します。
  • 合格条件の判定:
    • 科目Aの合格判定: 科目Aの合計素点がREQUIRED_RAW_SCORE_A(36点)以上であるかを確認します。
    • 科目Bの合格判定: 科目Bの合計素点がREQUIRED_RAW_SCORE_B(12点)以上であるかを確認します。
    • 両方の条件に合格した場合のみ、この1回の試行を「合格」と数え上げます。

3. 合格率の算出

上記の「1回の試行」を指定された回数(例: DEFAULT_TRIALS)繰り返します。 最終的に、「合格」と判定された試行の総数を、全試行回数で割ることで、合格率(パーセンテージ)を算出します。


(補足)本シミュレーターにおける「事前に知っている問題」の解釈について

本シミュレーターでは、科目Bを含む「事前に知っている問題」とは、受験者の方が「自身の知識と理解に基づいて、確実に正解できると確信している問題」と読み替えることを想定しています。

これにより、IRT採点の「難しい問題を正解すると高得点が得られる傾向」を素点計算上で近似的に表現しつつ、受験者の方が自身の得意分野や学習効果をシミュレーションに反映させ、より現実的な学習戦略を検討するための参考として活用いただけます。

📋ソース

プログラムコード(Java)
FeSimulator.java
--------------------------------------------------------------------------------------------
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.HashSet;
import java.util.stream.Collectors; // Stream API用に追加

/**
 * 基本情報技術者試験の合格確率をモンテカルロシミュレーションで計算するシミュレーター。
 * 各問題の配点設定に基づいた「素点計算」により合格率を算出します。
 * 本シミュレーターはIRT(項目応答理論)採点を再現するものではありません。
 */
public class FeSimulator {

    // 基本情報技術者試験の定数(素点計算に基づく)
    private static final int TOTAL_QUESTIONS_A = 60; // 科目A 総問題数
    private static final int CHOICES_A = 4; // 科目Aの選択肢数 (固定)
    private static final int SCORE_PER_QUESTION_A = 1; // 科目Aの各問題の配点 (素点)
    private static final int REQUIRED_RAW_SCORE_A = 36; // 科目Aの合格に必要な素点 (60点満点中36点)

    private static final int TOTAL_QUESTIONS_B = 20; // 科目B 総問題数
    private static final int SCORE_PER_QUESTION_B = 1; // 科目Bの各問題の配点 (素点)
    private static final int REQUIRED_RAW_SCORE_B = 12; // 科目Bの合格に必要な素点 (20点満点中12点)

    private static final int TOTAL_EXAM_QUESTIONS = TOTAL_QUESTIONS_A + TOTAL_QUESTIONS_B; // 試験全体の総問題数

    private static final int DEFAULT_TRIALS = 10000; // 各シナリオでのデフォルト試行回数

    /**
     * 各問題の定義。問題番号(※実際にはインデックス)、選択肢の数、配点を保持します。
     */
    public static class Problem {
        private final int no; // 問題番号(デバッグ用など)
        private final int choices; // 選択肢の数
        private final int score; // 配点

        public Problem(int no, int choices, int score) {
            this.no = no;
            this.choices = choices;
            this.score = score;
        }

        public int getNo() { return no; }
        public int getChoices() { return choices; }
        public int getScore() { return score; }
    }

    // 全問題データ(科目Aと科目Bを結合して、通し番号で管理)
    private static final List<Problem> PROBLEMS = new ArrayList<>();

    static {
        // 科目Aの問題 (No.1-60): 4択1点問題
        for (int i = 0; i < TOTAL_QUESTIONS_A; i++) {
            PROBLEMS.add(new Problem(i + 1, CHOICES_A, SCORE_PER_QUESTION_A));
        }

        // 科目Bの問題 (No.61-80, 元のNo.1-20): 選択肢数変動1点問題
        // 科目B選択肢数リスト = [6, 5, 7, 4, 7, 4, 6, 4, 4, 6, 4, 4, 4, 8, 4, 9, 10, 10, 5, 7]
        int[] choicesB = {6, 5, 7, 4, 7, 4, 6, 4, 4, 6, 4, 4, 4, 8, 4, 9, 10, 10, 5, 7};
        for (int i = 0; i < TOTAL_QUESTIONS_B; i++) {
            PROBLEMS.add(new Problem(TOTAL_QUESTIONS_A + i + 1, choicesB[i], SCORE_PER_QUESTION_B));
        }
    }

    /**
     * ランダム解答方式を定義する列挙型。
     * 各方式で、元の選択肢数から計算される有効な選択肢数を保持し、正答率を決定します。
     */
    public enum AnswerMethod {
        // 完全ランダム(不正解を0%消す力)
        FULL_RANDOM("0%の不正解を消す力(完全ランダム)", 0.0),
        // 不正解を25%消す力
        ELIMINATE_25_PERCENT("25%の不正解を消す力", 0.25),
        // 不正解を50%消す力
        ELIMINATE_50_PERCENT("50%の不正解を消す力", 0.50);

        private final String name;
        private final double eliminationRate; // 除外する不正解の割合

        AnswerMethod(String name, double eliminationRate) {
            this.name = name;
            this.eliminationRate = eliminationRate;
        }

        public String getName() {
            return name;
        }

        /**
         * 指定された問題の有効な選択肢数を計算します。
         * Math.round() を使用し、最小値は1とします。
         * @param originalChoices 元の選択肢の数
         * @return 計算された有効な選択肢の数
         */
        public int calculateEffectiveChoices(int originalChoices) {
            // 除外後の選択肢数を計算
            double remainingChoices = originalChoices * (1.0 - eliminationRate);
            // Math.round で丸め、小数点以下を四捨五入して整数にする
            int effectiveChoices = (int) Math.round(remainingChoices);
            // 少なくとも1つの選択肢は残るようにする
            return Math.max(1, effectiveChoices);
        }

        /**
         * ランダムに正解するかどうかを判定します。
         * @param random Randomインスタンス
         * @param problem 問題オブジェクト
         * @return 正解であればtrue、そうでなければfalse
         */
        public boolean isCorrect(Random random, Problem problem) {
            int effectiveChoices = calculateEffectiveChoices(problem.getChoices());
            // 0からeffectiveChoices-1までの乱数を生成し、0であれば正解とみなす
            return random.nextInt(effectiveChoices) == 0;
        }
    }

    /**
     * シミュレーション結果を保持するクラス。
     */
    public static class SimulationResult {
        private final int knownCorrectQuestionsOverall;
        private final double successRate;

        public SimulationResult(int knownCorrectQuestionsOverall, double successRate) {
            this.knownCorrectQuestionsOverall = knownCorrectQuestionsOverall;
            this.successRate = successRate;
        }

        public int getKnownCorrectQuestionsOverall() { return knownCorrectQuestionsOverall; }
        public double getSuccessRate() { return successRate; }
    }

    private final Random random;

    /**
     * FeSimulator の新しいインスタンスを生成します。
     */
    public FeSimulator() {
        this.random = new Random();
    }

    /**
     * 指定されたシナリオでモンテカルロシミュレーションを実行し、合格確率を計算します。
     *
     * @param answerMethod               シミュレーション対象の解答方式(ランダム解答の精度)
     * @param knownCorrectQuestionsOverall 事前に知っている正解数(試験全体に対する数)
     * @param trials                     試行回数
     * @return シミュレーション結果を表す {@code SimulationResult} オブジェクト
     * @throws IllegalArgumentException 不正な引数が指定された場合
     */
    public SimulationResult simulateScenario(AnswerMethod answerMethod, int knownCorrectQuestionsOverall, int trials) {
        if (knownCorrectQuestionsOverall < 0 || knownCorrectQuestionsOverall > TOTAL_EXAM_QUESTIONS) {
            throw new IllegalArgumentException(
                "事前に知っている正解数 (" + knownCorrectQuestionsOverall + ") は、0から総問題数 (" + TOTAL_EXAM_QUESTIONS + ") の範囲で指定してください。"
            );
        }
        if (trials <= 0) {
            throw new IllegalArgumentException("試行回数は1以上を指定してください。");
        }

        int successfulTrials = 0;

        // 試験全体の「事前に知っている問題総数」を科目Aと科目Bに按分
        int knownCorrectQuestionsA = (int) Math.round(knownCorrectQuestionsOverall * ((double) TOTAL_QUESTIONS_A / TOTAL_EXAM_QUESTIONS));
        int knownCorrectQuestionsB = knownCorrectQuestionsOverall - knownCorrectQuestionsA;

        // 科目ごとの上限チェック (念のため)
        knownCorrectQuestionsA = Math.min(knownCorrectQuestionsA, TOTAL_QUESTIONS_A);
        knownCorrectQuestionsB = Math.min(knownCorrectQuestionsB, TOTAL_QUESTIONS_B);


        for (int i = 0; i < trials; i++) {
            int currentScoreA = 0;
            int currentScoreB = 0;

            // 既に「事前に知っている問題」としてマークされた問題のインデックスを保持
            Set<Integer> knownCorrectIndicesA = new HashSet<>();
            Set<Integer> knownCorrectIndicesB = new HashSet<>();

            // 1. 「事前に知っている問題」の処理(科目A)
            List<Integer> questionIndicesA = new ArrayList<>();
            for (int k = 0; k < TOTAL_QUESTIONS_A; k++) {
                questionIndicesA.add(k);
            }
            Collections.shuffle(questionIndicesA, random); // 問題インデックスをシャッフル

            for (int k = 0; k < knownCorrectQuestionsA; k++) {
                int problemIndex = questionIndicesA.get(k); // シャッフルされたインデックス
                currentScoreA += PROBLEMS.get(problemIndex).getScore(); // その問題の配点を加算
                knownCorrectIndicesA.add(problemIndex); // 既に処理済みとしてマーク
            }

            // 2. 「事前に知っている問題」の処理(科目B)
            List<Integer> questionIndicesB = new ArrayList<>();
            // 科目Bの問題インデックスは、PROBLEMSリストの中での相対位置ではなく、科目B内での0からのインデックスで扱う
            for (int k = 0; k < TOTAL_QUESTIONS_B; k++) {
                questionIndicesB.add(k);
            }
            Collections.shuffle(questionIndicesB, random); // 問題インデックスをシャッフル

            for (int k = 0; k < knownCorrectQuestionsB; k++) {
                int problemIndexB_relative = questionIndicesB.get(k); // シャッフルされた科目B内でのインデックス
                int problemIndexInOverallList = TOTAL_QUESTIONS_A + problemIndexB_relative; // 全体リストでのインデックス
                currentScoreB += PROBLEMS.get(problemIndexInOverallList).getScore(); // その問題の配点を加算
                knownCorrectIndicesB.add(problemIndexB_relative); // 科目B内での相対インデックスをマーク
            }

            // 3. 「残りの問題」の処理(ランダム解答、科目A)
            for (int j = 0; j < TOTAL_QUESTIONS_A; j++) {
                if (!knownCorrectIndicesA.contains(j)) { // 事前に知っている問題でなければランダムに解答
                    Problem problem = PROBLEMS.get(j);
                    if (answerMethod.isCorrect(random, problem)) {
                        currentScoreA += problem.getScore(); // 正解なら配点を加算
                    }
                }
            }

            // 4. 「残りの問題」の処理(ランダム解答、科目B)
            for (int j = 0; j < TOTAL_QUESTIONS_B; j++) {
                if (!knownCorrectIndicesB.contains(j)) { // 事前に知っている問題でなければランダムに解答
                    Problem problem = PROBLEMS.get(TOTAL_QUESTIONS_A + j); // 全体リストから科目Bの問題を取得
                    if (answerMethod.isCorrect(random, problem)) {
                        currentScoreB += problem.getScore(); // 正解なら配点を加算
                    }
                }
            }

            // 5. 合格条件の判定
            boolean passedA = (currentScoreA >= REQUIRED_RAW_SCORE_A);
            boolean passedB = (currentScoreB >= REQUIRED_RAW_SCORE_B);

            if (passedA && passedB) {
                successfulTrials++;
            }
        }

        double successRate = (double) successfulTrials / trials * 100;
        return new SimulationResult(knownCorrectQuestionsOverall, successRate);
    }

    /**
     * シミュレーション結果を表示します。
     *
     * @param result 表示するシミュレーション結果
     */
    public void displayResult(SimulationResult result) {
        System.out.printf("・事前に%d問知っている場合: 合格率: %.2f%%\n",
                         result.getKnownCorrectQuestionsOverall(), result.getSuccessRate());
    }

    /**
     * メインメソッド。基本情報技術者試験の各種シナリオでシミュレーションを実行します。
     */
    public static void main(String[] args) {
        FeSimulator simulator = new FeSimulator();

        System.out.println("★基本情報技術者試験 突破確率計算:ランダム選択方式(モンテカルロシミュレーション)★");
        System.out.println("---");
        System.out.println("総問題数: " + TOTAL_EXAM_QUESTIONS + "問");
        System.out.println("科目A 合格に必要な素点: " + REQUIRED_RAW_SCORE_A + "点 / " + TOTAL_QUESTIONS_A + "点満点 (100点換算60点)");
        System.out.println("科目B 合格に必要な素点: " + REQUIRED_RAW_SCORE_B + "点 / " + TOTAL_QUESTIONS_B + "点満点 (100点換算60点)");
        System.out.println("---");
        System.out.println();

        // 各解答方式のシミュレーション
        for (AnswerMethod answerMethod : AnswerMethod.values()) {
            System.out.println("■" + answerMethod.getName() + " 試行結果");
            // knownCorrectQuestions は0問からTOTAL_EXAM_QUESTIONSまで繰り返す
            for (int i = 0; i <= TOTAL_EXAM_QUESTIONS; i++) {
                try {
                    SimulationResult result = simulator.simulateScenario(answerMethod, i, DEFAULT_TRIALS);
                    simulator.displayResult(result);
                } catch (IllegalArgumentException e) {
                    System.err.println("エラー: " + e.getMessage());
                }
            }
            System.out.println(); // 各解答方式の後に空行
        }
        System.out.println("---");
        System.out.println("※本シミュレーターは、基本情報技術者試験のIRT(項目応答理論)採点を厳密に再現するものではなく、");
        System.out.println("  各問題の配点が上記で設定された値であると仮定した「素点計算」に基づいています。");
        System.out.println("  実際の試験結果と異なる場合があることをご留意ください。");
    }
}

▶️WEB実行環境

glot.ioというWEB上でプログラムを実行できる環境があったため、誰でも動作確認ができるようにリンクを掲載しました。以下から実行(Run)できます。
https://glot.io/snippets/h9jqgijcdx

🧭実行結果

各1万回試行した、実行結果ログ ※長いので、折りたたみます。
★基本情報技術者試験 突破確率計算:ランダム選択方式(モンテカルロシミュレーション)★
---
総問題数: 80問
科目A 合格に必要な素点: 36点 / 60点満点 (100点換算60点)
科目B 合格に必要な素点: 12点 / 20点満点 (100点換算60点)
---

■0%の不正解を消す力(完全ランダム) 試行結果
・事前に0問知っている場合: 合格率: 0.00%
・事前に1問知っている場合: 合格率: 0.00%
・事前に2問知っている場合: 合格率: 0.00%
・事前に3問知っている場合: 合格率: 0.00%
・事前に4問知っている場合: 合格率: 0.00%
・事前に5問知っている場合: 合格率: 0.00%
・事前に6問知っている場合: 合格率: 0.00%
・事前に7問知っている場合: 合格率: 0.00%
・事前に8問知っている場合: 合格率: 0.00%
・事前に9問知っている場合: 合格率: 0.00%
・事前に10問知っている場合: 合格率: 0.00%
・事前に11問知っている場合: 合格率: 0.00%
・事前に12問知っている場合: 合格率: 0.00%
・事前に13問知っている場合: 合格率: 0.00%
・事前に14問知っている場合: 合格率: 0.00%
・事前に15問知っている場合: 合格率: 0.00%
・事前に16問知っている場合: 合格率: 0.00%
・事前に17問知っている場合: 合格率: 0.00%
・事前に18問知っている場合: 合格率: 0.00%
・事前に19問知っている場合: 合格率: 0.00%
・事前に20問知っている場合: 合格率: 0.00%
・事前に21問知っている場合: 合格率: 0.01%
・事前に22問知っている場合: 合格率: 0.02%
・事前に23問知っている場合: 合格率: 0.02%
・事前に24問知っている場合: 合格率: 0.01%
・事前に25問知っている場合: 合格率: 0.02%
・事前に26問知っている場合: 合格率: 0.11%
・事前に27問知っている場合: 合格率: 0.26%
・事前に28問知っている場合: 合格率: 0.28%
・事前に29問知っている場合: 合格率: 0.50%
・事前に30問知っている場合: 合格率: 0.87%
・事前に31問知っている場合: 合格率: 1.87%
・事前に32問知っている場合: 合格率: 2.68%
・事前に33問知っている場合: 合格率: 4.28%
・事前に34問知っている場合: 合格率: 5.88%
・事前に35問知っている場合: 合格率: 11.43%
・事前に36問知っている場合: 合格率: 15.64%
・事前に37問知っている場合: 合格率: 19.97%
・事前に38問知っている場合: 合格率: 23.73%
・事前に39問知っている場合: 合格率: 40.76%
・事前に40問知っている場合: 合格率: 47.17%
・事前に41問知っている場合: 合格率: 52.17%
・事前に42問知っている場合: 合格率: 55.50%
・事前に43問知っている場合: 合格率: 80.75%
・事前に44問知っている場合: 合格率: 83.08%
・事前に45問知っている場合: 合格率: 84.25%
・事前に46問知っている場合: 合格率: 84.98%
・事前に47問知っている場合: 合格率: 99.94%
・事前に48問知っている場合: 合格率: 100.00%
・事前に49問知っている場合: 合格率: 100.00%
・事前に50問知っている場合: 合格率: 100.00%
・事前に51問知っている場合: 合格率: 100.00%
・事前に52問知っている場合: 合格率: 100.00%
・事前に53問知っている場合: 合格率: 100.00%
・事前に54問知っている場合: 合格率: 100.00%
・事前に55問知っている場合: 合格率: 100.00%
・事前に56問知っている場合: 合格率: 100.00%
・事前に57問知っている場合: 合格率: 100.00%
・事前に58問知っている場合: 合格率: 100.00%
・事前に59問知っている場合: 合格率: 100.00%
・事前に60問知っている場合: 合格率: 100.00%
・事前に61問知っている場合: 合格率: 100.00%
・事前に62問知っている場合: 合格率: 100.00%
・事前に63問知っている場合: 合格率: 100.00%
・事前に64問知っている場合: 合格率: 100.00%
・事前に65問知っている場合: 合格率: 100.00%
・事前に66問知っている場合: 合格率: 100.00%
・事前に67問知っている場合: 合格率: 100.00%
・事前に68問知っている場合: 合格率: 100.00%
・事前に69問知っている場合: 合格率: 100.00%
・事前に70問知っている場合: 合格率: 100.00%
・事前に71問知っている場合: 合格率: 100.00%
・事前に72問知っている場合: 合格率: 100.00%
・事前に73問知っている場合: 合格率: 100.00%
・事前に74問知っている場合: 合格率: 100.00%
・事前に75問知っている場合: 合格率: 100.00%
・事前に76問知っている場合: 合格率: 100.00%
・事前に77問知っている場合: 合格率: 100.00%
・事前に78問知っている場合: 合格率: 100.00%
・事前に79問知っている場合: 合格率: 100.00%
・事前に80問知っている場合: 合格率: 100.00%

■25%の不正解を消す力 試行結果
・事前に0問知っている場合: 合格率: 0.00%
・事前に1問知っている場合: 合格率: 0.00%
・事前に2問知っている場合: 合格率: 0.00%
・事前に3問知っている場合: 合格率: 0.00%
・事前に4問知っている場合: 合格率: 0.00%
・事前に5問知っている場合: 合格率: 0.00%
・事前に6問知っている場合: 合格率: 0.00%
・事前に7問知っている場合: 合格率: 0.00%
・事前に8問知っている場合: 合格率: 0.00%
・事前に9問知っている場合: 合格率: 0.00%
・事前に10問知っている場合: 合格率: 0.00%
・事前に11問知っている場合: 合格率: 0.00%
・事前に12問知っている場合: 合格率: 0.00%
・事前に13問知っている場合: 合格率: 0.00%
・事前に14問知っている場合: 合格率: 0.00%
・事前に15問知っている場合: 合格率: 0.01%
・事前に16問知っている場合: 合格率: 0.07%
・事前に17問知っている場合: 合格率: 0.06%
・事前に18問知っている場合: 合格率: 0.09%
・事前に19問知っている場合: 合格率: 0.17%
・事前に20問知っている場合: 合格率: 0.17%
・事前に21問知っている場合: 合格率: 0.31%
・事前に22問知っている場合: 合格率: 0.51%
・事前に23問知っている場合: 合格率: 0.97%
・事前に24問知っている場合: 合格率: 1.22%
・事前に25問知っている場合: 合格率: 1.71%
・事前に26問知っている場合: 合格率: 2.59%
・事前に27問知っている場合: 合格率: 4.43%
・事前に28問知っている場合: 合格率: 6.08%
・事前に29問知っている場合: 合格率: 7.30%
・事前に30問知っている場合: 合格率: 9.17%
・事前に31問知っている場合: 合格率: 15.59%
・事前に32問知っている場合: 合格率: 19.18%
・事前に33問知っている場合: 合格率: 22.33%
・事前に34問知っている場合: 合格率: 25.74%
・事前に35問知っている場合: 合格率: 39.53%
・事前に36問知っている場合: 合格率: 43.57%
・事前に37問知っている場合: 合格率: 47.41%
・事前に38問知っている場合: 合格率: 50.05%
・事前に39問知っている場合: 合格率: 70.41%
・事前に40問知っている場合: 合格率: 71.93%
・事前に41問知っている場合: 合格率: 73.52%
・事前に42問知っている場合: 合格率: 74.72%
・事前に43問知っている場合: 合格率: 91.89%
・事前に44問知っている場合: 合格率: 91.88%
・事前に45問知っている場合: 合格率: 92.11%
・事前に46問知っている場合: 合格率: 92.85%
・事前に47問知っている場合: 合格率: 99.99%
・事前に48問知っている場合: 合格率: 100.00%
・事前に49問知っている場合: 合格率: 100.00%
・事前に50問知っている場合: 合格率: 100.00%
・事前に51問知っている場合: 合格率: 100.00%
・事前に52問知っている場合: 合格率: 100.00%
・事前に53問知っている場合: 合格率: 100.00%
・事前に54問知っている場合: 合格率: 100.00%
・事前に55問知っている場合: 合格率: 100.00%
・事前に56問知っている場合: 合格率: 100.00%
・事前に57問知っている場合: 合格率: 100.00%
・事前に58問知っている場合: 合格率: 100.00%
・事前に59問知っている場合: 合格率: 100.00%
・事前に60問知っている場合: 合格率: 100.00%
・事前に61問知っている場合: 合格率: 100.00%
・事前に62問知っている場合: 合格率: 100.00%
・事前に63問知っている場合: 合格率: 100.00%
・事前に64問知っている場合: 合格率: 100.00%
・事前に65問知っている場合: 合格率: 100.00%
・事前に66問知っている場合: 合格率: 100.00%
・事前に67問知っている場合: 合格率: 100.00%
・事前に68問知っている場合: 合格率: 100.00%
・事前に69問知っている場合: 合格率: 100.00%
・事前に70問知っている場合: 合格率: 100.00%
・事前に71問知っている場合: 合格率: 100.00%
・事前に72問知っている場合: 合格率: 100.00%
・事前に73問知っている場合: 合格率: 100.00%
・事前に74問知っている場合: 合格率: 100.00%
・事前に75問知っている場合: 合格率: 100.00%
・事前に76問知っている場合: 合格率: 100.00%
・事前に77問知っている場合: 合格率: 100.00%
・事前に78問知っている場合: 合格率: 100.00%
・事前に79問知っている場合: 合格率: 100.00%
・事前に80問知っている場合: 合格率: 100.00%

■50%の不正解を消す力 試行結果
・事前に0問知っている場合: 合格率: 0.16%
・事前に1問知っている場合: 合格率: 0.25%
・事前に2問知っている場合: 合格率: 0.26%
・事前に3問知っている場合: 合格率: 0.59%
・事前に4問知っている場合: 合格率: 0.59%
・事前に5問知っている場合: 合格率: 0.74%
・事前に6問知っている場合: 合格率: 0.84%
・事前に7問知っている場合: 合格率: 1.37%
・事前に8問知っている場合: 合格率: 1.84%
・事前に9問知っている場合: 合格率: 1.93%
・事前に10問知っている場合: 合格率: 2.20%
・事前に11問知っている場合: 合格率: 4.21%
・事前に12問知っている場合: 合格率: 4.45%
・事前に13問知っている場合: 合格率: 5.31%
・事前に14問知っている場合: 合格率: 5.80%
・事前に15問知っている場合: 合格率: 9.32%
・事前に16問知っている場合: 合格率: 10.81%
・事前に17問知っている場合: 合格率: 11.46%
・事前に18問知っている場合: 合格率: 12.63%
・事前に19問知っている場合: 合格率: 18.95%
・事前に20問知っている場合: 合格率: 20.16%
・事前に21問知っている場合: 合格率: 20.65%
・事前に22問知っている場合: 合格率: 21.68%
・事前に23問知っている場合: 合格率: 32.27%
・事前に24問知っている場合: 合格率: 33.53%
・事前に25問知っている場合: 合格率: 35.97%
・事前に26問知っている場合: 合格率: 36.86%
・事前に27問知っている場合: 合格率: 49.86%
・事前に28問知っている場合: 合格率: 51.69%
・事前に29問知っている場合: 合格率: 51.75%
・事前に30問知っている場合: 合格率: 52.47%
・事前に31問知っている場合: 合格率: 67.87%
・事前に32問知っている場合: 合格率: 68.30%
・事前に33問知っている場合: 合格率: 68.60%
・事前に34問知っている場合: 合格率: 68.97%
・事前に35問知っている場合: 合格率: 82.49%
・事前に36問知っている場合: 合格率: 82.35%
・事前に37問知っている場合: 合格率: 82.34%
・事前に38問知っている場合: 合格率: 83.29%
・事前に39問知っている場合: 合格率: 93.03%
・事前に40問知っている場合: 合格率: 93.17%
・事前に41問知っている場合: 合格率: 93.14%
・事前に42問知っている場合: 合格率: 92.83%
・事前に43問知っている場合: 合格率: 98.58%
・事前に44問知っている場合: 合格率: 98.43%
・事前に45問知っている場合: 合格率: 98.48%
・事前に46問知っている場合: 合格率: 98.31%
・事前に47問知っている場合: 合格率: 100.00%
・事前に48問知っている場合: 合格率: 100.00%
・事前に49問知っている場合: 合格率: 100.00%
・事前に50問知っている場合: 合格率: 100.00%
・事前に51問知っている場合: 合格率: 100.00%
・事前に52問知っている場合: 合格率: 100.00%
・事前に53問知っている場合: 合格率: 100.00%
・事前に54問知っている場合: 合格率: 100.00%
・事前に55問知っている場合: 合格率: 100.00%
・事前に56問知っている場合: 合格率: 100.00%
・事前に57問知っている場合: 合格率: 100.00%
・事前に58問知っている場合: 合格率: 100.00%
・事前に59問知っている場合: 合格率: 100.00%
・事前に60問知っている場合: 合格率: 100.00%
・事前に61問知っている場合: 合格率: 100.00%
・事前に62問知っている場合: 合格率: 100.00%
・事前に63問知っている場合: 合格率: 100.00%
・事前に64問知っている場合: 合格率: 100.00%
・事前に65問知っている場合: 合格率: 100.00%
・事前に66問知っている場合: 合格率: 100.00%
・事前に67問知っている場合: 合格率: 100.00%
・事前に68問知っている場合: 合格率: 100.00%
・事前に69問知っている場合: 合格率: 100.00%
・事前に70問知っている場合: 合格率: 100.00%
・事前に71問知っている場合: 合格率: 100.00%
・事前に72問知っている場合: 合格率: 100.00%
・事前に73問知っている場合: 合格率: 100.00%
・事前に74問知っている場合: 合格率: 100.00%
・事前に75問知っている場合: 合格率: 100.00%
・事前に76問知っている場合: 合格率: 100.00%
・事前に77問知っている場合: 合格率: 100.00%
・事前に78問知っている場合: 合格率: 100.00%
・事前に79問知っている場合: 合格率: 100.00%
・事前に80問知っている場合: 合格率: 100.00%

---
※本シミュレーターは、基本情報技術者試験のIRT(項目応答理論)採点を厳密に再現するものではなく、
各問題の配点が上記で設定された値であると仮定した「素点計算」に基づいています。
実際の試験結果と異なる場合があることをご留意ください。

いかがでしたでしょうか。
今回のシミュレーション結果で特に注目すべきは、解答の絞り込み能力が合否に与える大きな影響です。
※グラフがガタついているのは、正解を知っている問題を科目Aと科目Bに按分している境界が原因です。

🌧️厳しい現実:完全ランダムでは、運任せでは合格は困難

「0%の不正解を消す力(完全ランダム)」のシミュレーション結果は、合格への道のりが極めて険しい現実を示しています。このレベルにおいては、事前に33問の答えを確信できる知識があったとしても、合格率はわずか5%程度という厳しい数字に留まります。これは、単に多くの問題をこなすだけでは不十分であり、誤った選択肢を見抜く力がどれほど合否に影響するかを強く物語っています。

さらに、一切知識がない状態で完全にランダムにマークした場合の合格率が0%であることは、基本情報技術者試験が、単なる運任せでは決して突破できないという厳然たる現実を浮き彫りにしています。合格率を90%以上に引き上げるためには、このレベルでは総問題数80問中、おおよそ60%にあたる47問以上を確実に正解できる実力が必要となるようです。

☀️希望の光:50%の選択肢を絞り込む力で、現実的な合格ラインへ

一方で、「50%の不正解を消去できるレベル」に達すると、合格への道が現実的に見えてきます。このシミュレーション結果は、たとえ全問を完全に理解していなくとも、約半数の不正解選択肢を見抜く力が備わっていれば、事前に39問の知識があれば90%以上の合格率を達成可能であることを示しています。

これは、闇雲に全範囲を完璧にしようとするよりも、不確実な問題でも選択肢を絞り込む「確かな見極め力」を養うことが、合格への最も効果的な戦略となり得ることを強く示唆しています。過去問演習などを通じて、誤り選択肢を見抜く目を鍛えることが、あなたの合格を大きく引き寄せるでしょう。

🎯まとめ:確実な合格への道筋

今回のシミュレーション結果が明確に示しているのは、勉強せずに受験した場合の合格可能性はほぼゼロという厳しい現実です。完全ランダムでの合格率0%という数字は、基本情報技術者試験が決して運任せでは突破できない試験であることを物語っています。

しかし同時に、このシミュレーションは希望も示しています。適切な学習により「不正解選択肢を見抜く力」を身につければ、必要な知識量は大幅に軽減され、現実的な合格ラインに到達できることが分かりました。

合格への確実な道のり

  • 基礎知識の習得により「確実に解ける問題」を増やす
  • 過去問演習で「明らかに間違った選択肢」を見抜く力を養う
  • 焦らず計画的に学習を積み重ねる

基本情報処理を通して学習できるロジカルシンキングは、試験合格後も実務と趣味で役立つと思います。筆者自身も2007年の合格を通じてその価値を実感しており、このページを作成することができるぐらいの技量を手に入れ、さらに面白さを感じることができるようにもなりました。ぜひ皆さんにもじっくりと腰を据えて学習に取り組み、確実な合格を目指していただくとともに、自分が便利だな・楽しいなと思える何かを、作成できる力を手に入れていただければ幸いです。

※本シミュレーションが、あなたの学習計画立案の一助となれば幸いです。