Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1084to1088
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Problem mit Binominalkoeffizienten - Makro

Problem mit Binominalkoeffizienten - Makro
Jan
Hallo Forum
Habe lange im Internet gesucht und habe, glaube sogar im Archiv dieses Forums, folgende Datei gefunden:
https://www.herber.de/bbs/user/62835.xls
Mein Problem hier ist, das alles super funktioniert um die Binominalkoeffizienten zu berechnen, aber wenn ich ein sehr grosses m (um die 15000) und ein relativ grosses k (um die 1000) habe, dann stürzt mir immerr das Excel ab.
Gibt es da etwas, was man anpassen, ändern oder irgendwie anderst lösen könnte, damit ich noch grössere Werte erhalten kann?
Vielen Dank für eure Hilfe!
Gruss Jan
Falls es noch jemand interessiert:
Es ist sozusagen ein Lottoproblem mit 16000 Kugeln und davon sollen 1000 mit zurücklegen gezogen werden.
AW: Problem mit Binominalkoeffizienten - Makro
30.06.2009 11:41:07
Jogy
Hi.
Das habe ich zufällig gestern hier schon gepostet (kann natürlich dasselbe sein, wie in der _ Datei, aber ich kann hier nichts runterladen):

' Berechnet den Binomialkoeffizienten
Public Function BINOMIAL(ByVal n As Double, k As Double) As Variant
Dim i As Long
On Error GoTo errHand
' Mögliche Fehler abfangen
If Abs(CLng(n))  n Or Abs(CLng(k))  k Then
BINOMIAL = CVErr(xlErrNum)
' Bei k > n ist es null
ElseIf k > n Then
BINOMIAL = 0
' Berechnung des Binomialkoeffizienten
Else
' Da "n über k" = "n über (n - k)" wird das Minimum von
' k und n-k verwendet
If 2 * k > n Then k = n - k
' Startwert - bei k = 0 kommt 1 heraus
' (Algorithmus wird dann nicht mehr ausgeführt)
' Ansonsten ist der Startwert n bzw. bei k = 1
' bereits das Endergebnis (Algorithmus wird dann
' ebenfalls nicht mehr ausgeführt)
BINOMIAL = 1 + Sgn(k) * (n - 1)
' Alternativ
'        BINOMIAL = IIf(k > 0, n, 1)
' Berechnungalgorithmus (laut Wikipedia)
' Wird erst ab 2 ausgeführt, für 0 und 1 ist Startwert korrekt
For i = 2 To k
BINOMIAL = BINOMIAL / i * (n + 1 - i)
Next
End If
'ggf. Rückgabe Fehlerwert
errHand:
If Err.Number  0 Then BINOMIAL = CVErr(xlErrNum)
End Function


Deine Anforderungen erfüllt es aber nicht, da Excel solch große Zahlen nicht verarbeiten kann. Bei "1307 über 1000" bzw. "16000 über 121" ist Ende - das ist dann auch schon >10^307. "16000 über 1000" ist übrigens laut Windows Taschenrechner 4,6315328125107656507470368258168e+1622, das ist weit jenseits des Wertebereichs von Excel.
Gruss, Jogy

Anzeige
kleine Frage noch...
30.06.2009 12:12:28
Jan
Hallo Jogy
Vielen Dank für deine Funktion.
Habe doch noch eine Frage:
wenn ich "16000 über 1000" gleich wieder durch eine ähnlich grosse Zahl teilen würde, würde das irgendwie gehen? Resultat liegt dann zwischen 0 und 1....
Mein Ziel ist es wie oben schon erwähnt eine Wahrscheinlichkeit auszurechnen..
Vielen Dank für deine Unterstützung..
Gruss Jan
Übrigends, das gestern war auch ich..habe deine Funktion also schon ausprobiert, sie ist aber nicht exakt die seibe wie die andere.
Die andere, in meinem geposteten Dokument sieht so aus:
Option Explicit

Function mult_text(m1 As String, m2 As String) As String
Dim erg() As String
Dim rest() As Integer
Dim ii%, jj%, summ%
Application.Volatile
ReDim erg(Len(m2))
ReDim rest(Len(m2) + Len(m1) + 1)
For ii = 0 To Len(m2)
For jj = 1 To Len(m1) + Len(m2)
erg(ii) = erg(ii) & " "
Next jj
Next ii
For ii = 1 To Len(m2)
rest(0) = 0
For jj = Len(m1) To 1 Step -1
Mid(erg(ii), jj + ii, 1) = (Mid(m1, jj, 1) * Mid(m2, ii, 1) + rest(0)) Mod 10
rest(0) = Int((Mid(m1, jj, 1) * Mid(m2, ii, 1) + rest(0)) / 10)
Next jj
Mid(erg(ii), ii, 1) = rest(0)
Next ii
rest(0) = 0
For jj = Len(m1) + Len(m2) To 1 Step -1
summ = 0
For ii = 1 To UBound(erg)
summ = (IIf(Mid(erg(ii), jj, 1) = " ", 0, Mid(erg(ii), jj, 1)) * 1 + summ)
rest(jj) = IIf(Mid(erg(ii), jj, 1) = " ", 0, Mid(erg(ii), jj, 1)) * 1 + rest(jj)
Next ii
Mid(erg(0), jj, 1) = (summ + rest(jj + 1)) Mod 10
rest(jj) = Int((rest(jj) + rest(jj + 1)) / 10)
Next jj
While Left(erg(0), 1) = "0"
erg(0) = Right(erg(0), Len(erg(0)) - 1)
Wend
mult_text = erg(0)
End Function



Function fak_text(mm As String) As String
If mm > 1 Then
fak_text = mult_text(fak_text(mm - 1), mm)
Else
fak_text = 1
End If
End Function



Function koeff_Text(mm As String, nn As String) As String
Dim Zaehler() As Integer
Dim Nenner() As Integer
Dim ii%, jj%, kk%
Dim text As String, zz As String
ReDim Zaehler(nn)
ReDim Nenner(nn)
koeff_Text = "Nicht möglich!!!"
If nn * 1 > mm * 1 Then Exit Function
For ii = 1 To nn
Zaehler(ii) = mm - ii + 1
Nenner(ii) = ii
Next ii
For ii = nn To 1 Step -1
For kk = Nenner(ii) To 2 Step -1
For jj = 1 To nn
If Zaehler(jj) Mod kk = 0 And Nenner(ii) Mod kk = 0 Then
Zaehler(jj) = Zaehler(jj) / kk
Nenner(ii) = Nenner(ii) / kk
End If
Next jj
Next kk
Next ii
text = "1"
For ii = 1 To nn
zz = Zaehler(ii)
text = mult_text(zz, text)
Next
koeff_Text = text
End Function


Anzeige
AW: Problem mit Binominalkoeffizienten - Makro
30.06.2009 12:17:26
Jogy
Hi.
Hatte noch ne Idee... allerdings wird das alles, was zu groß für Excel ist als Text ausgegeben.

' Berechnet den Binomialkoeffizienten
Public Function BINOMIAL(ByVal n As Double, k As Double) As Variant
Dim i As Long
Dim addMantisse As Long
Dim tempString() As String
Dim nPotenz As Long
On Error GoTo errHand
' Mögliche Fehler abfangen
If Abs(CLng(n))  n Or Abs(CLng(k))  k Then
BINOMIAL = CVErr(xlErrNum)
' Bei k > n ist es null
ElseIf k > n Then
BINOMIAL = 0
' Berechnung des Binomialkoeffizienten
Else
' Da "n über k" = "n über (n - k)" wird das Minimum von
' k und n-k verwendet
If 2 * k > n Then k = n - k
' Startwert - bei k = 0 kommt 1 heraus
' (Algorithmus wird dann nicht mehr ausgeführt)
' Ansonsten ist der Startwert n bzw. bei k = 1
' bereits das Endergebnis (Algorithmus wird dann
' ebenfalls nicht mehr ausgeführt)
BINOMIAL = 1 + Sgn(k) * (n - 1)
' Alternativ
'        BINOMIAL = IIf(k > 0, n, 1)
' Berechnungalgorithmus (laut Wikipedia)
' Wird erst ab 2 ausgeführt, für 0 und 1 ist Startwert korrekt
For i = 2 To k
On Error Resume Next
BINOMIAL = BINOMIAL / i * (n + 1 - i)
' bei Fehler wird es durch die zu n nächstgrößere Zehnerpotenz geteilt
' und die Division gespeichert
If Err.Number  0 Then
On Error GoTo errHand
' Muss nur ein Mal bestimmt werden
If nPotenz = 0 Then
tempString = Split(Format(n, "0,0E+0"), "E+")
nPotenz = tempString(1) + 1
End If
addMantisse = addMantisse + nPotenz
BINOMIAL = BINOMIAL / 10 ^ nPotenz / i * (n + 1 - i)
End If
Next
End If
' Rückgabewert anpassen, wenn Mantisse verändert wurde
If addMantisse  0 Then
tempString = Split(BINOMIAL, "E+")
tempString(1) = tempString(1) + addMantisse
BINOMIAL = Join(tempString, "E+")
End If
'ggf. Rückgabe Fehlerwert
errHand:
If Err.Number  0 Then BINOMIAL = CVErr(xlErrNum)
End Function

Gruss, Jogy

Anzeige
AW: Problem mit Binominalkoeffizienten - Makro
30.06.2009 12:33:21
Jan
Hallo Jogy
dies könnte mich weiterbringen..
gibt es eine möglichkeit um zumbeispiel mit dem Resutat 3.60638462155241E+1645, welches ja jetzt als Text formatiert ist, weiterzurechnen?
Kann von mir aus auch gerundet sein...
Gruss Jan und Danke für deine Hilfe!
AW: Problem mit Binominalkoeffizienten - Makro
30.06.2009 12:46:54
Jogy
Hi.
Rechne doch einfach mit der Mantisse weiter, die Ordinate kannst Du ja später wieder dranhängen. Ach ja, mehr geltende Stellen als die vorhendenen geht nicht. Da müßtest Du dann den Windows Taschenrechner oder ein sonstiges Programm bzw. Programmiersprache nehmen, die mehr kann.
Gruss, Jogy
AW: Problem mit Binominalkoeffizienten - Makro
30.06.2009 13:01:16
Jan
Hallo Jogy..
geht leider nicht..gibt dann #Wert
werde es sonst irgendwie probieren..Vielen Dank für deine Hilfe!
Gruss Jan
Anzeige
AW: Problem mit Binominalkoeffizienten - Makro
30.06.2009 13:19:45
Jogy
Hi.
Wieso soll das nicht gehen? Kopier (Inhalte einfügen - Werte) doch einfach die Mantisse in eine Zelle, dann kannst Du wunderbar weiterrechnen. Am Schluss mus eben noch der Exponent dazu, das mußt Du dann natürlich wieder als Text formatieren. Oder rechne einfach in zwei Zellen, eine für den Exponenten und die andere für die Mantisse.
Die Mantisse bekommst Du mit
=--TEIL(D6;1;SUCHEN("E";D6)-1)
Den Exponenten mit
=--TEIL(D6;SUCHEN("E";D6)+1;LÄNGE(D6)-SUCHEN("E";D6))
Die Zelle mit der UDF mußt Du natürlich noch anpassen.
Gruss, Jogy
AW: Problem mit Binominalkoeffizienten - Makro
30.06.2009 13:32:06
Jan
Ah ok...Vielen Dank..hat geklappt!
Gruss Jan
Anzeige
AW: Korrektur
30.06.2009 16:00:36
Jogy
Hi.
Das Makro macht in der Form unter Umständen Rundungsfehler, nimm besser die Version:

' Berechnet den Binomialkoeffizienten
Public Function BINOMIAL(ByVal n As Double, k As Double) As Variant
Dim i As Long
Dim addExp As Long
Dim tempString() As String
Dim nPotenz As Long
On Error GoTo errHand
' Mögliche Fehler abfangen
If Abs(CLng(n))  n Or Abs(CLng(k))  k Then
BINOMIAL = CVErr(xlErrNum)
' Bei k > n ist es null
ElseIf k > n Then
BINOMIAL = 0
' Berechnung des Binomialkoeffizienten
Else
' Da "n über k" = "n über (n - k)" wird das Minimum von
' k und n-k verwendet
If 2 * k > n Then k = n - k
' Startwert - bei k = 0 kommt 1 heraus
' (Algorithmus wird dann nicht mehr ausgeführt)
' Ansonsten ist der Startwert n bzw. bei k = 1
' bereits das Endergebnis (Algorithmus wird dann
' ebenfalls nicht mehr ausgeführt)
BINOMIAL = 1 + Sgn(k) * (n - 1)
' Alternativ
'        BINOMIAL = IIf(k > 0, n, 1)
' Berechnungalgorithmus (laut Wikipedia)
' Wird erst ab 2 ausgeführt, für 0 und 1 ist Startwert korrekt
For i = 2 To k
On Error Resume Next
BINOMIAL = BINOMIAL * (n + 1 - i) / i
' bei Fehler wird es durch die zu n nächstgrößere Zehnerpotenz geteilt
' und die Division gespeichert
If Err.Number  0 Then
On Error GoTo errHand
' Muss nur ein Mal bestimmt werden
If nPotenz = 0 Then
tempString = Split(Format(n, "0,0E+0"), "E+")
nPotenz = tempString(1) + 1
End If
addExp = addExp + nPotenz
BINOMIAL = BINOMIAL / 10 ^ nPotenz * (n + 1 - i) / i
End If
Next
End If
' Rückgabewert anpassen, wenn Mantisse verändert wurde
If addExp  0 Then
' Ist evtl. noch eine Zahl
On Error Resume Next
BINOMIAL = BINOMIAL * 10 ^ addExp
' Wenn schon außerhalb des Wertebereichs, dann gibt es einen Fehler
' und muss als Text zurückgegeben werden
If Err.Number  0 Then
On Error GoTo errHand
tempString = Split(BINOMIAL, "E+")
tempString(1) = tempString(1) + addExp
BINOMIAL = Join(tempString, "E+")
End If
End If
'ggf. Rückgabe Fehlerwert
errHand:
If Err.Number  0 Then BINOMIAL = CVErr(xlErrNum)
End Function


Gruss, Jogy

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige