Zyklische Zahlen
(III)
C. 2 Word-Makros
I.
Charakterisierung
1.
Das erste Makro ermittelt zyklische Zahlen und trennt sie von den übrigen
Primzahlen. Sie werden in eine Datei c:/zypz.txt geschrieben und mit
"zy" bzw. "pr" gekennzeichnet.
2.
Das zweite Makro ermittelt das Verhältnis von zyklischen Zahlen 1. Ordnung
und höherer Ordnung. Sie werden aus c:/zypz.txt ausgelesen, die Verhältnisse
auf dem Bildschirm ausgegeben. Überprüfen Sie, daß zypz.txt nicht mit einer leeren Absatzmarke
abgeschlossen wird. Ich habe mir die diesbezüglichen Abfrageanweisungen erspart.
Der Programmteil ersetzt
"zy" und "pr" durch gr1$ und gr2$. Auf diese Weise können
Zahlengruppen auch ein anderes "Präfix" erhalten. Die beiden Präfixe
"zy" und "pr" sind am Anfang als gr1$ und gr2$ deklariert.
Es ist zu beachten, daß das Makro immer mit gr2$ beginnt. Da die Reihenfolge
der Zahlen keine Rolle spielt, stellt man an die Spitze eine Zahl mit der
Kennzeichnung unter gr2$.
3.
Beide
Makros bestehen aus einem kommentierten Teil und dem eigentlichen Programmteil.
Der kommentierte Teil ist unter Word 7 programmiert, der Programmteil ist unter
Word 2000 konvertiert.
4.
Falls
Sie nicht wissen, wie die Makros erstellt werden, gebe ich den Weg an:
Kopieren Sie das Makro in die
Zwischenablage. Dann gehen Sie zu Menü Extras > Makro > Makros. Geben Sie
in die Eingabezeile einen beliebigen Namen mit der Erweiterung .MAIN (z.B.
a.MAIN) für das Makro an und drücken auf Erstellen. Löschen Sie den
vorgegebenen Eintrag und fügen Sie den Inhalt der Zwischenablage ein. Drücken
Sie auf das Speichersymbol und schließen Sie Visual-Basic.
Nun können Sie das Makro laufen
lassen. Leider weiß ich bis heute nicht, wie man ein Endlosmakro und Word 2000+
anders als durch Strg-Alt-Entf beenden kann. Da das erste Makro die Ergebnisse
in eine Datei schreibt, geht durch die erzwungene Schließung des Programms
nichts verloren. Sichern Sie sich unbedingt die Textdatei mit den zyklischen Zahlen.
Wenn Sie zu einem anderen
Zeitpunkt das Programm fortsetzen wollen, geben Sie die letzte Zahl der
Textdatei + 2 unter der numerischen Variablen z ein, u.U. können Sie auch eine anderen Dateinamen wählen.
II.
Makrodokumentierung
1a) Kommentierung
'Basisprogramm zur Ermittlung von zyklischen Zahlen
Dim Shared z, n
Sub MAIN
z = 7:n = 3
Gegeben sind die ersten 4 Primzahlen 1,2,3,5
'z = die zu teilende ungerade Zahl, die um jeweils 2 Zähler fortschreitet; 7 ist die erste zu berechnende Zahl
'n = 3: der erste ungerade Divisor, der um jeweils 2 Zähler fortschreitet
einfügen
"pr" + Mid$(Str$(1), 2): EinfügenAbsatz
einfügen
"pr" + Mid$(Str$(2), 2) :EinfügenAbsatz
einfügen
"pr" + Mid$(Str$(3), 2) : EinfügenAbsatz
einfügen
"pr" + Mid$(Str$(5), 2) :EinfügenAbsatz)
'Die ersten 4 Zahlen werden vorgegeben und mit "pr" bezeichnet. Die Zahl 3 ist zyklisch 2. Ordnung.
start:
If z > 1000 Then Goto
ENDE
e = z / n
'e = Teilungsergebnis, es ist immer eine Dezimalzahl
If Int(e) <> e Then
'Int() liefert den ganzzahligen Teil einer Dezimalzahl
If n * n > z Then
UPZYK
Goto START
Else
'Wenn das Teilungsergebnis eine ganze Zahl ist, ist die geteilte Zahl keine Primzahl und die übernächste Zahl wird geteilt
n = n + 2 : Goto START
EndIf
Else
z = z + 2 : n = 3 : Goto START
EndIf
ende:
End Sub
'------------------
Sub UPZYK
'Es wird untersucht, ob die ermittelte Primzahl eine zyklische Zahl 1. Ordnung ist.
r = 1
'r = Rest; r = 1: die erste Stelle 1 ist als erster Rest anzusehen, der am Ende der Teilungen wiederkehrt
stz = Len(Mid$(Str$(z), 2))
'stz = Stellenzahl. Die Periodik einer zyklischen Zahl p (1. Ordnung) besteht aus p-1 Stellen. Sie wird aus der Zahl 10p-1 ermittelt. Die erste Teilung des Programms überspringt die Nullen nach dem Komma, die jeweils um einen Zähler weniger als die Stellenzahl der zu teilenden Zahl betragen, z.B. 23: nach dem Komma steht 2-1=1 Null: 0,043...
For i = 1 To stz
r = r * 10
Next
'Die Zahl,
durch die z geteilt wird besteht aus 1 + n Nullen. n ist gleich
der Stellenzahl von z., z.B. 10/7.
div = r / z
'div: Teilungsergebnis, gleichbedeutend mit der Variablen e des Hauptprogramms
rest = r - Int(div) * z
'z.B. 10/7 = 1,42857; 10-(1*7) = 3; rest = 3
While rest > 1
div = rest * 10 / z
stz = stz + 1
rest = rest * 10 - Int(div) * z
If stz > (z - 1) / 2 Then
einfügen "zy" + Mid$(Str$(z), 2) : Print
Str$(z):EinfügenAbsatz
Goto
WEITER
EndIf
'if: Sobald die Stellenzahl für eine zyklische Zahl 2. Ordnung überschritten ist, handelt es sich um eine zyklische Zahl 1. Ordnung. Die Zahl 13 z.B. ist eine Zahl 2. Ordnung, ihre Stellenzahl (13-1)/2 = 6. Der if-Einschub verkürzt die Ermittlung von zyklischen Zahlen 1. Ordnung um die Hälfte. Die zyklischen Zahlen 1. Ordnung erhalten die Kennzeichnung "zy".
Wend
Einfügen "pr" + Mid$(Str$(z), 2):EinfügenAbsatz
'Die zyklischen Zahlen höherer Ordnung
erhalten die Kennzeichnung "pr".
WEITER:
z = z + 2 : n = 3
1b) Programm
Dim
z, n
Public
Sub MAIN()
Dim
e
z =
0
n =
0
z =
7: n = 3
Open
"c:/zykpmz.txt" For Output As 1
Print #1, "pr" +
Mid(Str(1), 2)
Print #1, "pr" + Mid(Str(2), 2)
Print #1, "pr" + Mid(Str(3), 2)
Print #1, "pr" + Mid(Str(5), 2)
start:
e =
z / n
If
WordBasic.Int(e) <> e Then
If n * n > z Then
UPZYK
GoTo start
Else
n = n + 2: GoTo start
End If
Else
z = z + 2: n = 3: GoTo start
End
If
ende:
End
Sub
'------------------
Private Sub UPZYK()
Dim r
Dim stz
Dim i
Dim div
Dim rest
r = 1
stz = Len(Mid(Str(z), 2))
For
i = 1 To stz
r = r * 10
Next
div
= r / z
rest
= r - WordBasic.Int(div) * z
While
rest > 1
div = rest * 10 / z
stz = stz + 1
rest = rest * 10 - WordBasic.Int(div) * z
If stz > (z - 1) / 2 Then
Print #1, "zy" + Mid(Str(z), 2):
WordBasic.PrintStatusBar Str(z)
GoTo WEITER
End If
Wend
Print #1, "pr" + Mid(Str(z), 2):
WordBasic.PrintStatusBar Str(z)
WEITER:
z = z + 2: n = 3
End Sub
2a) Kommentierung
'Dieses Programm liest zyklische Zahlen 1. und höherer Ordnung aus einer Datei und stellt ihr Zahlenverhältnis zu einander fest. Die zyklischen Zahlen sind mit "zy" am Anfang (ohne Leerzeichen), die übrigen Primzahlen mit "pr" gekennzeichnet. Nach dem Wechsel eines Zahlengruppe bleibt die letzte Zahl der ersten Gruppe "stehen", während die Zahlen der zweiten Gruppe so lange fortschreiten, bis die nächste Zahl der ersten Gruppe eingelesen ist. Jede der fortschreitenden Zahlen wird mit der stehenden Zahl ins Verhältnis gesetzt. Z.B. bleibt die 5. zyklische Zahl 29 stehen, während die nicht-zyklischen Zahlen 1. Ordnung 31, 37, 41, 43 fortschreiten. Die Zahl 37 ist die 8. nicht-zyklische Zahl 1. Ordnung, daher bildet sie mit der zyklischen Zahl 29 das Verhältnis 8:5.
Dim Shared zy$, pr$, zyk$, prz$, zyn, prn
Sub MAIN
FormatTabulator
.AlleLösch
FormatTabulator
.Position = "2 cm", .Ausrichten = 0, .Bestimmen
FormatTabulator .Position = "4 cm",
.Ausrichten = 0, .Bestimmen
Open "c:/ww2/werte/zykpz.txt" For Input As
#1
Line Input #1, zypz$
prn
= prn + 1
'prn = Nummer der Primzahlen: Die Zahlen 1,2,5 sind nicht zyklisch und können frei auf die beiden Gruppen aufgeteilt werden. Das Programm rechnet sie den zyklischen Zahlen höherer Ordnung zu.
While Left$(zypz$, 2) = "pr"
prn = prn + 1
Line Input #1,
zypz$
pr$
= zypz$
Wend
prn = prn - 1
'While-Wend stellt erst nach Einlesen des anderen Zahlentyps den Wechsel fest, daher muß die Zählung um 1 zurückgesetzt werden. Diese erste While-Wend -Schleife gilt nur für den Anfang der Zählung, daher liegt START: vor der zweiten WW-Schleife.
zy$ = zypz$ :
zyn = zyn + 1
'Die eingelesene Zahl wird dem zweiten Typ zy$ hinzugerechnet.
START:
While Left$(zypz$, 2) = "zy"
Line Input #1,
zypz$
zyn = zyn + 1
If Left$(zypz$,
2) = "zy" Then
zy$ = zypz$ :
zyk$ = zy$ : UPFZ
'zy$ wird zu zyk$ weiter umbenannt, da zypz$ durch das Einlesen einer weiteren Zahl neu bestimmt wird. Dasselbe gilt für pr$ imd prz$. Im Unterprogramm Faktorenzerlegung UPFZ wird das Verhältnis der fortschreitenden Zahl zur stehenden Zahl ermittelt.
EndIf
Wend
zyn = zyn - 1
pr$ = zypz$ : prz$ = pr$ : prn = prn + 1 : UPFZ
While Left$(zypz$, 2) = "pr"
Line Input #1,
zypz$
prn = prn + 1
pr$ = zypz$
If Left$(zypz$, 2) = "pr"
Then
pr$ = zypz$ : prz$ = pr$
UPFZ
EndIf
Wend
prn = prn - 1
zy$ = zypz$ :
zyk$ = zy$ : zyn = zyn + 1 : UPFZ
Goto START
'Die beiden Zahlentypen wechseln sich mit gleichem Muster in zwei WW-Schleifen ab.
ende:
End Sub
'------------------
Sub UPFZ
'Stop : Print zyn, prn, zyk$, prz$
Dim f(30)
'f() = Einlesen von Faktoren
z = zyn : p =
prn
'Umbenennung zu z und p, um aktuellen Inhalt von zyn und prn zu erhalten.
'Die Faktorenzerlegung wird an der kleineren zyklischen Anzahl z vorgenommen.
START1:
e = z / 2
'Sonderbehandlung der geraden Zahl 2, danach Wechsel zu ungeraden Zahlen mit 3 und d = d+2
Print e, z
If e = Int(e) Then
n
= n + 1 : f(n) = 2
z = z / 2
Goto START1
Else
Print n
d = 3
'd = divisor
EndIf
START2:
e = z / d
If e = Int(e) Then
n
= n + 1 : f(n) = d
z = z / d
Print n, z
Goto START2
Else
d = d + 2
If d * d > z
Then
n
= n + 1 : f(n) = z
ElseIf z = d Then
n = n + 1 :
f(n) = d
Else
Goto START2
EndIf
EndIf
'Programm zur Ermittlung gemeinsamer Faktoren
'Die gefundenen Faktoren werden mit den Faktoren der größeren Primzahlanzahl p verglichen.
gem = 1 : z =
1
'gem = gemeinsame Faktoren, z = Faktoen, die nicht in p enthalten sind.
1 ist Multiplikationsfaktor, p = jeweiliger Rest
For i = 1 To n
e = p / f(i)
If e = Int(e) Then
gem = gem *
f(i) : p = p / f(i)
Else
z = z * f(i)
EndIf
Next
If gem > 50 Then
'Die Größe der gemeinsamen Faktoren kann hier eingestellt werden.
Einfügen
Mid$(Str$(z), 2) + Chr$(9) + Mid$(Str$(p), 2) + Chr$(9) + Mid$(Str$(gem), 2)
Einfügen
Chr$(9) + zyk$ + Chr$(9) + prz$
'Der Reihe nach werden ausgegeben: die Verhältniszahlen der kleineren und der größeren Gruppe, die gemeinsamen Faktoren, die letzte Zahl der jeweiligen Gruppe. Die dazwischen stehenden Tabulatoren ermöglichen die Umwandlung in eine Tabelle mit entsprechenden Sortiermöglichkeiten.
EndIf
End Sub
2b) Programm
Dim zy$, pr$, zyk$, prz$, zyn, prn
Public
Sub MAIN()
Dim gr1$
Dim gr2$
Dim zypz$
zy$ = ""
pr$ = ""
zyk$ = ""
prz$ = ""
zyn
= 0
prn
= 0
gr1$
= "zy": gr2$ = "pr"
Close
On
Error GoTo -1: On Error GoTo ende
Open
"c:/zypz.txt" For Input As 1
Line
Input #1, zypz$
If zypz$ = "" Then GoTo ende
prn = prn + 1
While
WordBasic.[Left$](zypz$, 2) = gr2$
prn = prn + 1
Line Input #1, zypz$
pr$ = zypz$
Wend
prn = prn - 1
zy$ = zypz$: zyk$ = zy$: zyn = zyn + 1
START:
While
WordBasic.[Left$](zypz$, 2) = gr1$
Line Input #1, zypz$
zyn = zyn + 1
If WordBasic.[Left$](zypz$, 2) = gr1$ Then
zy$ = zypz$: zyk$ = zy$: UPFZ
End If
Wend
zyn = zyn - 1
pr$ = zypz$: prz$ = pr$:
prn = prn + 1: UPFZ
While
WordBasic.[Left$](zypz$, 2) = gr2$
Line Input #1, zypz$
prn = prn + 1
pr$ = zypz$
If WordBasic.[Left$](zypz$, 2) = gr2$
Then
pr$ = zypz$: prz$ = pr$
UPFZ
End If
Wend
prn = prn - 1
zy$
= zypz$: zyk$ = zy$: zyn = zyn + 1: UPFZ
GoTo
START
ende:
End
Sub
'------------------
Private Sub UPFZ()
Dim z
Dim p
Dim e
Dim n
Dim d
Dim gem
Dim i
ReDim f__(30)
z =
zyn: p = prn
START1:
e =
z / 2
If e
= WordBasic.Int(e) Then
n = n + 1: f__(n) = 2
z = z / 2
GoTo START1
Else
d = 3
End
If
START2:
e =
z / d
If e
= WordBasic.Int(e) Then
n = n + 1: f__(n) = d
z = z / d
GoTo START2
Else
d = d + 2
If d * d > z Then
n = n + 1: f__(n) = z
ElseIf z = d Then
n = n + 1: f__(n) = d
Else
GoTo START2
End If
End
If
gem
= 1: z = 1
For
i = 1 To n
e = p / f__(i)
If e = WordBasic.Int(e) Then
gem = gem * f__(i): p = p / f__(i)
Else
z = z * f__(i)
End If
Next
If
gem > 50 Then
WordBasic.Insert
Mid(Str(z), 2) + Chr(9) + Mid(Str(p), 2) + Chr(9) + Mid(Str(gem), 2)
WordBasic.Insert
Chr(9) + zyk$ + Chr(9) + prz$
WordBasic.InsertPara
End
If
End Sub
Erstellt: Februar 2006