Exakte Berechnung der unvollständigen Betafunktion Βₓ(a,b) und Iₓ(a,b)
mit ganzzahligen Koeffizienten und rationalem x

Die englische Wikipedia schreibt (ohne weitere Begründung):

For positive integer a and b, the incomplete beta function will be a polynomial of degree a + b - 1 with rational coefficients.

Ins Deutsche übersetzt:

⟪ Β_x(a,b) = sum_(i=0)^(a+b-1) k_i x^i " mit " k_i in QQ ⟫

Das prüfen wir doch einmal nach.

1. Umformung der Integral-Darstellung von Βₓ(a,b) mit ganzzahligen a und b zu einem Polynom

Schauen wir uns die Definition von Βₓ(a,b) an:

(1) ⟪ Β_x(a,b) = int_0^x t^(a-1) (1-t)^(b-1) dt ⟫

Um die Potenz von 1 - t zu beseitigen, nutzen wir die erweiterte binomische Formel:

(2) ⟪ (x + y)^m = sum_(i=0)^m ((m),(i)) \ x^(m-i) \ y^i ⟫

Und wenden sie mit x := 1, y := -t und m := b-1 an:

(3) ⟪ Β_x(a,b) = int_0^x t^(a-1) sum_(i=0)^(b-1) ((b-1),(i)) \ 1^(b-1-i) \ (-t)^i \ dt ⟫

⟪ Β_x(a,b) = int_0^x t^(a-1) sum_(i=0)^(b-1) ((b-1),(i)) \ (-t)^i \ dt ⟫

⟪ Β_x(a,b) = int_0^x t^(a-1) sum_(i=0)^(b-1) ((b-1),(i)) \ (-1)^i \ t^i \ dt ⟫

Wir ziehen das t a - 1 in die Summe und erhalten so eine Gleichung, in der nur noch ein Faktor von t abhängt:

(4) ⟪ Β_x(a,b) = int_0^x sum_(i=0)^(b-1) (-1)^i \ ((b-1),(i)) \ t^(a-1+i) \ dt ⟫

Nach Vertauschen von Integral und Summation können wir integrieren.

(5) ⟪ Β_x(a,b) = sum_(i=0)^(b-1) (-1)^i \ ((b-1),(i)) \ int_0^x t^(a-1+i) \ dt ⟫

Mit ∫xn = xn+1 / (n+1) erhalten wir:

(6) ⟪ Β_x(a,b) = sum_(i=0)^(b-1) (-1)^i \ ((b-1),(i)) \ x^(a+i) / (a+i) ⟫

Substitution von i durch i-a ergibt:

⟪ Β_x(a,b) = sum_(i=a)^(a+b-1) (-1)^(i-a) \ ((b-1),(i-a)) \ 1/i \ x^i ⟫

(7) ⟪ Β_x(a,b) = sum_(i=0)^(a+b-1) k_i \ x^i " mit " k_i = { ( (-1)^(i-a) \ ((b-1),(i-a)) \ 1/i, if i ge a ), ( 0 , if i lt a ) :} ⟫

Et voilà, da ist die Darstellung als Polynom mit rationalen Koeffizienten; und die höchste Potenz von x ist offensichtlich a+b-1. ☺

2. Berechnung für x = 1

Für x = 1 vereinfacht sich die Formel (6) ein wenig:

(8) ⟪ Β_1(a,b) = sum_(i=0)^(b-1) (-1)^i ((b-1),(i)) 1/(a+i) ⟫

Schauen wir uns die Funktionswerte für kleine Werte von a und b an:

b
a 1 2 3 4 5 6 7 8
1 1/1 1/2 1/3 1/4 1/5 1/6 1/7 1/8
2 1/2 1/6 1/12 1/20 1/30 1/42 1/56 1/72
3 1/3 1/12 1/30 1/60 1/105 1/168 1/252 1/360
4 1/4 1/20 1/60 1/140 1/280 1/504 1/840 1/1320
5 1/5 1/30 1/105 1/280 1/630 1/1260 1/2310 1/3960
6 1/6 1/42 1/168 1/504 1/1260 1/2772 1/5544 1/10296
7 1/7 1/56 1/252 1/840 1/2310 1/5544 1/12012 1/24024
8 1/8 1/72 1/360 1/1320 1/3960 1/10296 1/24024 1/51480
Tabelle 1: Werte von Β1(a,b) als Brüche.

Die Funktion ist wie zu erwarten symmetrisch. Wir können so erweitern, dass der Nenner zu (a-b-1)! wird:

b
a 1 2 3 4 5 6 7 8
1 1
1!
1
2!
2
3!
6
4!
24
5!
120
6!
720
7!
5040
8!
2 1
2!
1
3!
2
4!
6
5!
24
6!
120
7!
720
8!
5040
9!
3 2
3!
2
4!
4
5!
12
6!
48
7!
240
8!
1440
9!
10080
10!
4 6
4!
6
5!
12
6!
36
7!
144
8!
720
9!
4320
10!
30240
11!
5 24
5!
24
6!
48
7!
144
8!
576
9!
2880
10!
17280
11!
120960
12!
6 120
6!
120
7!
240
8!
720
9!
2880
10!
14400
11!
86400
12!
604800
13!
7 720
7!
720
8!
1440
9!
4320
10!
17280
11!
86400
12!
518400
13!
3628800
14!
8 5040
8!
5040
9!
10080
10!
30240
11!
120960
12!
604800
13!
3628800
14!
25401600
15!
Tabelle 2: Werte von Β1(a,b) als auf (a+b-1)! erweiterte Brüche.

Die Zähler jeder Zeile betragen jeweils ein Vielfaches der Zähler der vorausgehenden Zeile, und die Zähler der Zeile a=1 haben jeweils den Wert (b-1)!. Versuchen wir also, im Zähler (b-1)! auszuklammern:

b
a 1 2 3 4 5 6 7 8
1 1 · 0!
1!
1 · 1!
2!
1 · 2!
3!
1 · 3!
4!
1 · 4!
5!
1 · 5!
6!
1 · 6!
7!
1 · 7!
8!
2 1 · 0!
2!
1 · 1!
3!
1 · 2!
4!
1 · 3!
5!
1 · 4!
6!
1 · 5!
7!
1 · 6!
8!
1 · 7!
9!
3 2 · 0!
3!
2 · 1!
4!
2 · 2!
5!
2 · 3!
6!
2 · 4!
7!
2 · 5!
8!
2 · 6!
9!
2 · 7!
10!
4 6 · 0!
4!
6 · 1!
5!
6 · 2!
6!
6 · 3!
7!
6 · 4!
8!
6 · 5!
9!
6 · 6!
10!
6 · 7!
11!
5 24 · 0!
5!
24 · 1!
6!
24 · 2!
7!
24 · 3!
8!
24 · 4!
9!
24 · 5!
10!
24 · 6!
11!
24 · 7!
12!
6 120 · 0!
6!
120 · 1!
7!
120 · 2!
8!
120 · 3!
9!
120 · 4!
10!
120 · 5!
11!
120 · 6!
12!
120 · 7!
13!
7 720 · 0!
7!
720 · 1!
8!
720 · 2!
9!
720 · 3!
10!
720 · 4!
11!
720 · 5!
12!
720 · 6!
13!
720 · 7!
14!
8 5040 · 0!
8!
5040 · 1!
9!
5040 · 2!
10!
5040 · 3!
11!
5040 · 4!
12!
5040 · 5!
13!
5040 · 6!
14!
5040 · 7!
15!
Tabelle 3: Werte von Β1(a,b) als auf (a+b-1)! erweiterte Brüche, b! ausgeklammert.

Offensichtlich ist der rot markierte erste Term jeweils gleich (a-1)!:

b
a 1 2 3 4 5 6 7 8
1 0! 0!
1!
0! 1!
2!
0! 2!
3!
0! 3!
4!
0! 4!
5!
0! 5!
6!
0! 6!
7!
0! 7!
8!
2 1! 0!
2!
1! 1!
3!
1! 2!
4!
1! 3!
5!
1! 4!
6!
1! 5!
7!
1! 6!
8!
1! 7!
9!
3 2! 0!
3!
2! 1!
4!
2! 2!
5!
2! 3!
6!
2! 4!
7!
2! 5!
8!
2! 6!
9!
2! 7!
10!
4 3! 0!
4!
3! 1!
5!
3! 2!
6!
3! 3!
7!
3! 4!
8!
3! 5!
9!
3! 6!
10!
3! 7!
11!
5 4! 0!
5!
4! 1!
6!
4! 2!
7!
4! 3!
8!
4! 4!
9!
4! 5!
10!
4! 6!
11!
4! 7!
12!
6 5! 0!
6!
5! 1!
7!
5! 2!
8!
5! 3!
9!
5! 4!
10!
5! 5!
11!
5! 6!
12!
5! 7!
13!
7 6! 0!
7!
6! 1!
8!
6! 2!
9!
6! 3!
10!
6! 4!
11!
6! 5!
12!
6! 6!
13!
6! 7!
14!
8 7! 0!
8!
7! 1!
9!
7! 2!
10!
7! 3!
11!
7! 4!
12!
7! 5!
13!
7! 6!
14!
7! 7!
15!
Tabelle 4: Werte von Β1(a,b) als Fakultäten in a und b

Die Funktionswerte für kleine a und b legen nahe, dass gilt:

(9) ⟪ Β_1(a,b) ≟ ((a-1)! (b-1)!) / ((a+b-1)!) ⟫

3. Beweis von Β1(a,b) = (a-1)! * (b-1)! / (a+b-1)!

Wegen der Summe in der Darstellung von Β1(a,b) bietet sich ein Induktionsbeweis über b an.

Wir verankern bei b = 1:

(10) ⟪ Β_1(a,[1]) = sum_(i=0)^([1]-1) (-1)^i (([1]-1),(i)) 1/(a+i) = (-1)^0 ((0),(0)) 1/a = 1/a = ((a-1)! ([1]-1)!) / ((a+[1]-1)!) ✓ ⟫

Für den Induktionsschritt nutzen wir eine Eigenschaft des Binomialkoeffizienten:

⟪ ((n+1),(k+1)) = ((n),(k+1)) + ((n),(k)) ⟫

Dabei erlauben wir k = -1, um ein unübersichtliches Herumgewürge mit Indizes zu vermeiden:

⟪ ((n),(-1)) := 0 ⟫

⟪ 1 = ((n+1),(0)) = ((n),(0)) + ((n),(-1)) = 1 + 0 = 1 ⟫

Für b + 1 erhalten wir:

(11) ⟪ Β_1(a,b+1) = sum_(i=0)^(b) (-1)^i ((b),(i)) 1/(a+i) ⟫

(12) ⟪ Β_1(a,b+1) = sum_(i=0)^(b) (-1)^i ((b-1),(i)) 1/(a+i) + sum_(i=0)^(b) (-1)^i ((b-1),(i-1)) 1/(a+i) ⟫

In der linken Summe können wir den letzten Summanden und in der rechten Summe den ersten Summanden streichen, weil der jeweilige Binomialkoeffizient 0 ist:

⟪ Β_1(a,b+1) = sum_(i=0)^(b-1) (-1)^i ((b-1),(i)) 1/(a+i) + sum_(i=1)^(b) (-1)^i ((b-1),(i-1)) 1/(a+i) ⟫

In der rechten Summe substituieren wir i durch i + 1:

⟪ Β_1(a,b+1) = sum_(i=0)^(b-1) (-1)^i ((b-1),(i)) 1/(a+i) + sum_(i=0)^(b-1) (-1)^(i+1) ((b-1),(i)) 1/(a+(i+1)) ⟫

Wir ziehen ein -1 aus der rechten Summe:

⟪ Β_1(a,b+1) = sum_(i=0)^(b-1) (-1)^i ((b-1),(i)) 1/(a+i) - sum_(i=0)^(b-1) (-1)^i ((b-1),(i)) 1/((a+1)+i) ⟫

Und haben damit eine Rekursionsformel:

(13) ⟪ Β_1(a,b+1) = Β_1(a,b) - Β_1(a+1,b) ⟫

Jetzt müssen wir nur noch einsetzen:

⟪ Β_1(a,[b+1]) = ((a-1)! \ (b-1)!) / ((a+b-1)!) - (([a+1]-1)! \ (b-1)!) / (([a+1]+b-1)!) ⟫

⟪ Β_1(a,[b+1]) = ((a-1)! \ (b-1)! \ (a+b)) / ((a+b-1)! \ (a+b)) - (a! \ (b-1)!) / ((a+b)!) ⟫

⟪ Β_1(a,[b+1]) = ((a-1)! \ (b-1)! \ (a+b) - a \ (a-1)! \ (b-1)!) / ((a+b)!) ⟫

⟪ Β_1(a,[b+1]) = ((a-1)! \ (b-1)! \ (a+b - a )) / ((a+b)!) = ((a-1)! \ b! ) / ((a+b)!) ⟫

⟪ Β_1(a,[b+1]) = ((a-1)! \ ([b+1]-1)! ) / ((a+[b+1]-1)!) ✓ ⟫

Zusammen mit (10) haben wir (9) bewiesen. ☺

4. Effiziente Berechnung

Wenn wir für mehrere xj gleichzeitig rechnen, brauchen wir C(i) und p(i) nur einmal zu bestimmen:

(14) ⟪ Β_(x_j)(a,b) = sum_(i=0)^(b-1) (-1)^i \ ubrace( ubrace( ((b-1),(i)))_(C(i)) \ 1/(a+i) )_(p(i)) \ ubrace( x_j^(a+i))_(X_j(i)) ⟫

Die Faktoren C(i) und Xj(i) können inkrementell berechnet werden:

(15)

⟪ C(0) = ((b-1),(0)) = 1 ⟫

⟪ C(i+1) = ((b-1),(i+1)) = (b-1-i)/(i+1) \ ((b-1),(i)) = (b-1-i)/(i+1) \ C(i) ⟫

⟪ X_j(0) = x_j^a ⟫

⟪ X_j(i+1) = X_j(i) \ x_j ⟫

Um gemeinsame Ausdrücke nur einmal zu berechnen, führen wir eine Hilfsvariable ein:

(16) ⟪ p(i) = C(i) // (a+i) ⟫

Und summieren folgende Terme auf:

(17) ⟪ s_j(i) = p(i) \ X_j(i) ⟫

Das ergibt folgenden Algorithmus:

function beta( x[], a, b ){

	// Berechne C(0) und Xj(0)
	C  := 1
	Xj := pow(xj, a)
	i  := 0

	// Berechne p(0) und initialisiere Βj(0)
	p  := C / (a+i)
	Βj := p * Xj

	while( i < b-1 ){

		// Berechne C(i+1) und Xj(i+1)
		C  := C * (b-1-i) / (i+1)
		Xj := Xj * xj
		i  := i + 1

		// Berechne p(i) und aktualisiere Βj(i)
		p  := C / (a+i)
		if odd(i)
			Βj := Βj - p * Xj
		else
			Βj := Βj + p * Xj
		endif
	}

	return Β[]
}
Algorithmus 1: naive Berechnung von Βx(a,b)

5. Online-Ausführung von Algorithmus 1

Bei Werten ab etwa 10 für a und b führt diese naive Implementierung mit double-Genauigkeit zu unakzeptablen bis absurden Rechenfehlern, verursacht durch extreme Unterschiede der Größenordnungen der Summanden.
Nicht nachmachen!

Weil die Werte von Βx(a,b) rasch sehr klein werden, wird auch der normalisierte Wert Ix(a,b)=Βx(a,b)/Β1(a,b) angezeigt.

Βx1(a,b)
Βx2(a,b)
Β1(a,b)
Ix1(a,b)
Ix2(a,b)
min(|summands|)
max(|summands|)
max / min

6. Exakte Berechnung für große Werte von a und b und rationale Werte von x

Für rationale Werte von x ist der Wert des Polynomes (6) als Summe von Produkten rationaler Zahlen wieder rational und damit exakt berechenbar.

A straightforward binomial expansion of the integrand and a subsequent term-by-term integration results in an alternating series in powers of x which cannot be used for large values of a. The eventual subtraction of consecutive terms of nearly equal absolute values causes a prohibitive loss in significant digits.
A. R. DiDonato and M. P. Jarnagin (1967)

Hehe, doch genau das machen wir jetzt.

Dabei vermeiden wir einen Signifikanz-Verlust, indem wir mit exakten rationalen und natürlichen Zahlen rechnen, und bekommen so ein exaktes Ergebnis. Wobei dieses im allgemeinen ein Bruch mit sehr großem Zähler und Nenner sein wird. 🤪

Die rationalen Zahlen werden als Produkt von Primzahlpotenzen mit ganzzahligem, auch negativem Exponent dargestellt:

⟪ q = prod_i p_i^(e_i) " mit " p_i in bbb "P", e_i in ZZ⟫

Beispiele: 20 = 22 · 51, 24 = 23 · 31, 100 = 22 · 52, 1/2 = 2-1, 2/3 = 21 · 3-1, 4/9 = 22 · 3-2.

Die ganzzahlige Werte i, i+1, a+i und b-1-i des Algorithmus werden vor Verwendung durch Primfaktorzerlegung in die Darstellung als Produkt von Primzahlpotenzen konvertiert.

Multiplikationen und Divisionen von Zahlen in dieser Darstellung sind sehr schnell, wobei das Kürzen automatisch erfolgt, anders als bei der Darstellung als Paar von zwei beliebig genauen ganzen Zahlen. Das gilt auch für die Berechnung des kleinsten gemeinsamen Vielfaches oder des größten gemeinsamen Teiler.

Leider lassen sich Zahlen in dieser Darstellung nicht addieren oder subtrahieren, diese müssen zuerst in ein Darstellung als Polynom überführt werden, in der Addition und Subtraktionen trivial sind:

⟪ n = sum_j d_j K^j " mit " d_j in NN_0, 0 le d_j lt K⟫

Und in der Tat braucht diese Konversion, die implizit bei der Summation über S[i] * N im zweiten Teil des Algorithmus durchgeführt wird, den größten Teil der Laufzeit.

function beta( x, a, b ){

	// (1) Berechne Summanden als exakte rationale Zahlen S = Sz/Sn

	// Berechne C(0) und X(0)
	C := 1        // oder (a+b-1)!/(a-1)!/(b-1!) für Berechnung von Iₓ(a,b)
	X := pow(x, a)
	i := 0

	// Berechne und speichere Summanden
	S[0] := C / (a+i) * X

	while( i < b-1 ){

		// Berechne C(i+1) und Xj(i+1)
		C := C * (b-1-i) / (i+1)
		X := X * x
		i := i + 1

		// Berechne und speichere Summanden
		S[i] := C / (a+i) * X
	}

	// (2) Mache die Summanden ganzzahlig und addiere sie

	// bestimme kleinstes gemeinsames Vielfaches N der Nenner der Summanden
	N := kgvi( numerator(Si) )

	// multipliziere Summanden mit N, addiere die (ganzzahligen) Produkte
	Z := ∑i( S[i] * N )

	// betaₓ(a,b) ist exakt Z/N
	return ( Z, N )
}
Algorithmus 2: exakte Berechnung von Βx(a,b) und Ix(a,b)

Die Dezimaldarstellung des Bruch bekommt man durch Multiplikation des Zählers Z mit der passenden Zehnerpotenz, ganzzahliger Division des Produktes durch den Nenner N und Einfügen des Dezimalpunktes. Um einen gerundeten Wert zu bekommen, addiert man vor der Division die Hälfte des Nenners zum Zähler.

Den Wert der regularisierten Beta-Funktion Ix(a,b) bekommt man durch Division von Βx(a,b) durch Β1(a,b).

7. Online-Ausführung der exakten Berechnung

Benutzt ganze Zahlen und rationale Zahlen mit unbegrenzter Genauigkeit.

Eine Berechnung kann sehr lange dauern, deshalb wird wird sie von einem Webworker durchgeführt und es wird ein Fortschrittsbalken angezeigt.

Da immer zuerst das exakte Ergebnis bestimmt wird, hat die gewählte Zahl signifikanter Ziffern der Dezimaldarstellung praktisch keinen Einfluss auf die Rechenzeit.

Ix(a,b):

Exakte Darstellung als rationale Zahl

Zähler:

Nenner:

Βx(a,b):

Exakte Darstellung als rationale Zahl

Zähler:

Nenner: