詳細な説明は、以下の解説記事をご覧ください。

javascriptにより、ブラウザから実行できるプログラムです。単一のhtmlファイルですので、何をしているのかはソースを見れば分かります。

一応、安全性は確認しておりますが、バグやファイル改ざん等のリスクまでは対応できません。利用する際には自己責任でお願い致します。このプログラムの使用に関して、当方は一切の責任を負いません。

古いブラウザだと動かないかもしれません。

対局数が多い場合には、処理に時間がかかることがあります。

英語版の表記は以下の意味です。

  • 「games」:対局数。
  • 「wins」:勝ち数。
  • 「draws」:引き分け数。
  • 「confidence interval」:信頼区間。
  • 「Calculate」:計算実行。
  • 「Select all」:全選択。
  • 「winning percentage」:勝率。
  • 「standard error」:標準誤差。
  • 「relative Elo rating」:相対イロレーティング。

「removed from games」は引き分けを対局数から取り除く場合、「transformed into (draws / 2) wins」は引き分け数の半分(端数は切り捨て)を勝ち数に加える場合に選択してください。

このプログラムは、パブリックドメイン(公有)扱いとします。ご自由にお使いください。

以下はc++版の関数です。やっていることは基本的にjavascript版と同じですが、コメントが付いています。

#include <algorithm> // std::minとstd::maxのため。windows.hの名前衝突に注意。
#include <cmath> // 数学関数のため。

// ----------------------------------------------
double log10_binomial(const int & n, const int & k)
// 二項係数 C(n, k) の常用対数。
// ----------------------------------------------
{
	const int m = std::min(k , (n - k));

	double s = 0.0;

	for (int i = 1; i <= m; i++)
	{
		s += std::log10((n - m + i) / double(i));
		// オーバーフロー対策で対数での計算。
		// 常識的な範囲の計算なら対数を取らずに掛け算のやり方でもよい。
		// javascript版では場合分けで少し高速化。
	}

	return(s);
}

// ----------------------------------------------
double binomial_distribution(const int & n, const int & k, const double & p)
// 二項分布 C(n, k) * p^{k} * (1 - p)^{n - k} の値。
// ----------------------------------------------
{
	return(std::pow(10.0, (log10_binomial(n, k) + k * std::log10(p) + (n - k) * std::log10(1.0 - p))));
	// オーバーフロー対策で対数での計算。
}

// ----------------------------------------------
void confidence_interval(const int & n, const int & k, const double & a, double & p, double & p_min, double & p_max, double & dr, double & dr_min, double & dr_max)
// 入力:対局数n、勝利数k、[100 * (1 - a)]%信頼区間のa。
// 出力:勝率推定値p、勝率下限値p_min、勝率上限値p_max、レート差推定値dr、レート差下限値dr_min、レート差上限値dr_max。
// ----------------------------------------------
{
	if ((n < 5) || (k <= 0) || (k >= n) || (a <= 0.0) || (a >= 1.0))
	{
		// 本来はエラー処理、ここでは省略。
		return;
	}

	// 勝率推定。
	p = k / double(n);

	// 挟み撃ちで区間を絞っていくための初期値。
	int k_min = 0;
	int k_max = n;

	// 区間境界での二項分布の値の初期値。
	double b_min = binomial_distribution(n, k_min, p);
	double b_max = binomial_distribution(n, k_max, p);

	// 確率の積算値。0から始めて、a越えを目指す。
	double s = 0.0;

	while (true) // a超えまでの無限ループ。
	{
		// 境界の分布値が小さい方を狭めていく。
		if (b_min < b_max)
		{
			s += b_min;
			if (s >= a) {break;} // 超えたら抜ける。越える前が信頼区間。
			k_min++;
			b_min = binomial_distribution(n, k_min, p);
		}
		else
		{
			s += b_max;
			if (s >= a) {break;} // 超えたら抜ける。越える前が信頼区間。
			k_max--;
			b_max = binomial_distribution(n, k_max, p);
		}
	}

	// 区間を勝率に直す。
	p_min = k_min / double(n);
	p_max = k_max / double(n);

	// レート差の計算。
	dr = 400.0 * std::log10(p / (1 - p));
	dr_min = (k_min == 0) ? -1.E308 : (400.0 * std::log10(p_min / (1 - p_min)));
	dr_max = (k_max == n) ?  1.E308 : (400.0 * std::log10(p_max / (1 - p_max)));
	// 念のために対数の発散を避けているが、普通の環境なら不要。

	return;
}