組み込みの埋まってるとこ

システム寄りの組み込みCプログラミングBLOG

ドント方式で選挙の当選者を決定するプログラム

令和7年度大学入学共通テストからの出題教科・科目である情報のサンプル問題を題材に、 ドント方式で当選政党を決定する選挙の当選者決定プログラムをつくってみました。 C言語で書かれていますが基本的なプログラムなのでJavaPython等他の言語でも参考になるでしょう。

プログラムの解説

アルゴリズムの解説は大学入試センターにある試験問題の本文をご覧ください。

令和7年度以降の試験に向けた検討について|大学入試センター

プログラムソース

ドント方式で当選政党を決定する選挙のC言語での解答例です。

#include <stdio.h>

#define NUM_OF_PARTY 4  /* 政党数 */
#define NUM_OF_SEAT  6  /* 選挙で選ばれる定員数 */

int main()
{
    /* 政党名と投票数のデータ */
    const char *party[NUM_OF_PARTY] = {
        "A Party","B Party", "C Party", "D Party"
    };
    int vote[NUM_OF_PARTY] = {
        1200, 660, 1440, 180
    };


    /* 総投票数を計算する */
    int amount = 0;
    for (int m = 0; m < NUM_OF_PARTY; m++) {
        amount += vote[m];
    }
    printf("Amount of vote: %d\n", amount);

    /* 当選政党を決めるときの比較に使う値を初期化する */
    double weight[NUM_OF_PARTY];
    for (int m = 0; m < NUM_OF_PARTY; m++) {
        weight[m] = (double)vote[m];
    }

    /* 政党ごとの当選者数を初期化する */
    int elect[NUM_OF_PARTY];
    for (int m = 0; m < NUM_OF_PARTY; m++) {
        elect[m] = 0;
    }

    /* すべての議席が埋まるまで当選政党を決定する */
    for (int seat = 0; seat < NUM_OF_SEAT; seat++) {
        /* 投票数を現時点での当選者数で割った値が一番大きな政党を当選とする */
        int maxParty = 0;
        for (int m = 0; m < NUM_OF_PARTY; m++) {
            if (weight[m] > weight[maxParty]) {
                maxParty = m;
            }
        }
        /* 当選政党の当選者数と比較値を更新する */
        elect[maxParty] += 1;
        weight[maxParty] = (double)vote[maxParty]/(double)(elect[maxParty] + 1);

#ifdef DEBUG
        printf("Term %d:", seat+1);
        printf(" Hikaku=");
        for (int i = 0; i < NUM_OF_PARTY; i++) {
            printf("%9.0f,", weight[i]);
        }
        printf(" Tosen=");
        for (int i = 0; i < NUM_OF_PARTY; i++) {
            printf("%7d,", elect[i]);
        }
        printf("\n");
#endif
    }

    /* 結果発表 */
    for (int m = 0; m < NUM_OF_PARTY; m++) {
        printf("%s: %d seat\n", party[m], elect[m]);
    }

    return 0; /* main関数正常終了 */
}

プログラムの応用方法

政党と定員はdefineの値だけで変更できるようにプログラムが工夫されています。 ただしこれに伴う政党名と投票数のデータの修正は必要になります。

プログラムの課題

どの政党の当選者名簿にも十分な人数の立候補者がいて、当選政党に選ばれたとき議席配分ができないことは起こらない前提で省略されている処理があります。これはいつか改良すべきです。

最後の当選者を決めるとき、同じ投票数の政党が複数あった場合はプログラム的なデータの検索順で議席が割り当てられます。極端な例では定員が1名で政党が2つあってどちらの政党も同じ投票数であったとき、何も警告を出さずに最初に検索された政党に議席を割り当て何事もなかったかのように終了してしまいます。これもいつか改良すべきです。

プログラムの考察

総投票数はint型の変数amountで表しています。 int型の範囲は-2147483648~2147483647ですので有権者数が日本の参議院比例代表ぐらいの規模の選挙であれば十分に計算可能です。計算の途中でオーバーフローが起こらないこともレビューでは確認しています。

投票数を当選者数で除算しているところがありますが、ここはdouble型で計算しています。 int型で除算した場合は少数点以下の数字が切り捨てになるため正確に比較できないケースが起こり得ると考えられそれを回避するためです。 double型であれば仮数部のビット数がint型のビット数よりも大きいため、今回のようにint型の投票数を除算した値で比較する用途であれば理論的に計算後の量子誤差は無視することが可能です。float型は仮数部のビット数がint型のビット数よりも小さいため、結果の有効ビット数が元のint型のビット数を下回ることになってしまい期待どおり比較することができません。