Hallo ihr Lieben, ich habe ein etwas mathematisches Problem für euch. Ich versuche die Anzahl aller möglichen Teiler für eine natürliche Zahl zu finden. Dazu zerlege ich eine beliebige Zahl in ihre Primfaktoren, daraus kann man die Teiler bilden. Z.B. für die Zahl 360 sind die Primfaktoren 2^3 * 3^2 * 5. Die Teiler kann man nun durch geschicktes kombinieren der Primfaktoren ermitteln. Hier eine Liste aller Teiler für die Zahl 360:
2^1 = 2
2^2 = 4
2^3 = 8
3^1 = 3
3^2 = 9
5^1 = 5
2^1 * 3^1 = 6
2^2 * 3^1 = 12
2^3 * 3^1 = 24
2^1 * 5^1 = 10
2^2 * 5^1 = 20
2^3 * 5^1 = 40
3^1 * 5^1 = 15
3^2 * 5^1 = 45
2^1 * 3^1 * 5^1 = 30
2^2 * 3^1 * 5^1 = 60
2^3 * 3^1 * 5^1 = 120
2^1 * 3^2 * 5^1 = 90
2^2 * 3^2 * 5^1 = 180
2^3 * 3^2 * 5^1 = 360
Alles anzeigen
Zusätzlich muss noch die 1 als Teiler beachtet werden, insgesamt existieren also 21 mögliche Teiler für die Zahl 360. Die Frage ist jedoch nun, wie man das am besten ausrechnet? Man benötigt im Grunde ja nur die Anzahl der Primfaktoren (3) und die Anzahl der Exponenten jedes Primfaktor (3, 2 und 1). Folgenden Ansatz habe ich bisher, jedoch ist die Funktion _GetComb() falsch da ich nicht richtig rechne. Diese Funktion soll mir letztendlich nur die Anzahl der Teiler zurückgeben, welche das sind ist letztendlich für meine Zwecke egal. Hier der Sourcecode:
[autoit]; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +
[/autoit][autoit][/autoit][autoit]#include <Array.au3>
[/autoit][autoit][/autoit][autoit]Global $aiNumFact = _GetNumbPrimeFact(360)
_ArrayDisplay($aiNumFact) ; Anzahl der Exponenten ist korrekt! 3, 2 und 1...
; Hier müsste eigentlich 21 heraus kommen...
ConsoleWrite(_GetComb($aiNumFact) & @CRLF)
; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +
[/autoit][autoit][/autoit][autoit]Func _GetNumbPrimeFact($iNumb) ; Exponenten der Primfaktoren bestimmen
Local $aiFact[Int(Sqrt($iNumb))]
Local $iDiv = 3
Local $iCount, $fSqrt
If Not Mod($iNumb, 2) Then
While Not Mod($iNumb, 2)
$aiFact[0] += 1
$iNumb /= 2
WEnd
$iCount = 1
EndIf
$fSqrt = Sqrt($iNumb)
While $iNumb <> 1 And $iDiv <= $fSqrt
If Not Mod($iNumb, $iDiv) Then
$aiFact[$iCount] = 1
$iNumb /= $iDiv
While Not Mod($iNumb, $iDiv)
$aiFact[$iCount] += 1
$iNumb /= $iDiv
WEnd
$fSqrt = Sqrt($iNumb)
$iCount += 1
EndIf
$iDiv += 2
WEnd
If $iNumb <> 1 Then
$aiFact[$iCount] = 1
$iCount += 1
EndIf
ReDim $aiFact[$iCount]
Return $aiFact
EndFunc
; Diese Funktion macht mir Probleme und Kopfschmerzen...
Func _GetComb(ByRef $aiFact) ; Anzahl der möglichen Teiler
Local $iSize = UBound($aiFact)
Local $iFac = $aiFact[0]
Local $iAdd = $aiFact[0]
Local $iC, $iSum, $iAdd
For $iC = 2 To $iSize
$iSum += _C($iSize, $iC)
$iFac *= $aiFact[$iC -1]
$iAdd += $aiFact[$iC -1]
Next
Return $iSum * $iFac + $iAdd +1
EndFunc
Func _C($n, $k) ; Kombination
Return _P($n) / (_P($n - $k) * _P($k))
EndFunc
Func _P($n) ; Permutation
Local $iRet = 1
While $n > 1
$iRet *= $n
$n -= 1
WEnd
Return $iRet
EndFunc
; ++++++++++ +++++++++ ++++++++ +++++++ ++++++ +++++ ++++ +++ ++ +
[/autoit]Ich hoffe jemand kann mir helfen. Das muss doch mit Stochastik irgendwie zu berechnen sein. Irgendwas mit Permutation, Kombination und/oder Variation muss doch passen damit ich das richtige Ergebnis heraus bekomme. Weiß jemand Rat?