| Autor |
Beitrag |
sennaheu
      
Beiträge: 22
|
Verfasst: Mo 10.03.03 14:29
so, habe eine neue aufgabe bekommen *g*
diesmal sollen wir eine function schreiben, die möglichst SCHNELL herausfindet, ob eine Zahl eine Primzahl ist, oder nicht.
unser leerer, äh, lehrer hat uns das vorgegeben:
Quelltext 1:
| function IstPrim (zahl:LongInt): boolean; |
diese function ist jedoch ein sogenanntes "unterprogramm". sie arbeitet also "selbständig". eingabe und ausgabe sollen also separat stattfinden.
wobei das jetzt eher unwichtig ist. die hauptaufgabe besteht darin eine möglichst schnelle function zu schreiben, die überprüft ob eine zahl eine primzahl ist oder nicht, wie ich ja bereits schon sagte. 
|
|
DaFox
      
Beiträge: 189
|
Verfasst: Mo 10.03.03 14:48
Hi.
Schnell soll wohl heißen, dass Du die Überprüfung nur bis sqrt(zahl) machen sollst, denn das reicht aus (mathematisch beweisbar  )
Gruß,
Markus
|
|
GSE
      
Beiträge: 740
Win 2k, Win XP Pro
D5 Prof, D6 Ent, D2k5 PE
|
Verfasst: Mo 10.03.03 17:30
Wer hat´s erfunden? Die Schweizer: www.swissdelphicente.../showcode.php?id=914
(Nach unten scrollen)
mfg
GSE
_________________ Programming today is a race between software engineers striving to build bigger and better idiot-proof programs
and the universe trying to produce bigger and better idiots. So far, the universe is winning. (Richard Cook)
|
|
sennaheu 
      
Beiträge: 22
|
Verfasst: Mo 10.03.03 19:31
hey, vielen dank für die schnelle hilfe
hier nochmal der quelltext, da ich ein paar fragen dazu habe:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| function IsPrime(Prim: Longint): Boolean; var Z: Real; Max: LongInt; Divisor: LongInt; begin Prime := False; if (Prim and 1) = 0 then Exit; Z := Sqrt(Prim); Max := Trunc(Z) + 1; Divisor := 3; while Max > Divisor do begin if (Prim mod Divisor) = 0 then Exit; Inc(Divisor, 2); if (Prim mod Divisor) = 0 then Exit; Inc(Divisor, 4); end; Prime := True; end; |
Wenn ich den Text so übernehme, meckert delphi, dass direkt nach dem beginn "prime" nicht definiert sei. dies ist ja auch der fall. wenn ich also das "e" nach prime weglasse, meckert es bzg. inkompatible typen von integer und boolean. ich weiss, dass hört sich jetzt noobisch an, ist es aber auch
was mach ich da falsch? bin ich einfach zu blöd um das zu kapieren?
ausserdem habe ich probleme die einzelnen schritte nachzuvollziehen. so verstehe ich zum beispiel nicht, wieso es am anfang "prim and 1" heist.
mein lehrer wird mich nicht ernstnehmen, wenn ich ihm das programm nicht erklären kann...
kann mir da jemand helfen?
so, jetzt zur praktischen umsetzung. um dieses programm zu testen benötige ich ja eingabe und ausgabe. eingabe ist in diesem fall ein edit und ausgabe die caption des buttons (ja oder nein). ich definiere also zunächst mal das edit in der function des button1.click. jetzt aber die grosse frage: wie gebe ich diesen wert an die function IsPrim weiter?
ich weiss, sind viele noob-fragen, aber wie ich schon sagte, beschäftige ich mich erst seit kurzem mit dem thema und hinke deshalb im unterricht hinterher. ich versuche aber mit aller gewalt wenigstens etwas licht in das dunkle zu bringen...
|
|
mars
      
Beiträge: 238
Debian Woody, Win 2000, Win XP
D7 Ent, Kylix 3
|
Verfasst: Mo 10.03.03 19:36
Erstens zu prime: musst du einfach durch Result ersetzen. Zu (Prime and 1): Dieser Ausdruck testet ob es sich um eine ganze Zahl handelt. Übergeben kannst du folgendermassen: IsPrim(StrToInt(Edit1.TExt));
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Mo 10.03.03 22:53
Dies ist der Miller-Rabin-Primzahl-Test.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50:
| function zeuge(z,n: LongInt) : Boolean; VAR c, erg, alt,temp : Int64; i : Integer; bit : ARRAY[0..63] OF Boolean; begin erg:=1; for i:=0 TO 63 DO bit[i]:=false; c:=n-1; i:=0; while c>0 do begin bit[i]:=(c mod 2 = 1); c:=c shr 1; i:=i+1; end; i:=i-1; while i>=0 DO begin
alt:=erg; erg:=(alt*alt) mod n; if (erg =1) and (alt <>1) and (alt <> n-1) then begin result:=true; exit; end; if bit[i] then erg:=(erg*z) mod n; i:=i-1; end; result:=(erg<>1); end;
function ist_prim(n,k : LongInt) : Boolean; VAR z,i : LongInt; begin i:=0; while i<k do begin z:=Random(2147483647); if n<>4 then z:=z mod (n-4); z:=z+2; if zeuge(z,n) then begin result:=false; exit; end; i:=i+1; end; result:=true; end; |
Beruht auf folgender Tatsache. Ist n eine Primzahl, so gilt für jede a aus den natürlichen Zahlen: a^(n-1) mod n = 1. Zusammen mit einem Satz aus der linearen Algebra (um die Sicherheit zu steigern), konnten Miller und Rabin den Test oben bauen. Bei ist_prim ist n die zu testende Zahl und k die Anzahl der Tests. Die Wahrscheinlichkeit, dass eine als prim befundene Zahl nicht prim ist, ist maximal 1/(2^k). Wenn Du den Test 30mal machst, kannst Du sagen: das Ergebnis ist richtig!
MfG,
Peter
P.S.: ich habe den Quelltext aus einem Javaprogramm übersetzt, welches ich vor einem Jahr geschrieben habe. Seit dem habe ich auch keine Java mehr gemacht. Es können also noch kleine Fehler drin sein. Werde morgen nochmal sorgfältig nachschauen.
<edit>
ACHTUNG: Quelltext korrigiert, damit er mit großen Zahlen funktioniert!
</edit>
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
sennaheu 
      
Beiträge: 22
|
Verfasst: Di 11.03.03 16:01
so, danke,
habe mal ein bischen rumprobiert. das programm läuft, oder bzw. es werden keine fehlermeldungen mehr angezeigt
was mich allerdings konfus macht, ist, dass immer nur "nein" angezeigt wird. also irgendetwas stimmt nicht. ich konnte bis jetzt aber den fehler nicht finden.
vielleicht sieht jemand von euch was ich falsch gemacht habe:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37:
| var Form1: TForm1; Result: Boolean; implementation
{$R *.DFM}
function IsPrime(Prim: Longint): Boolean; var Z: Real; Max: LongInt; Divisor: LongInt; begin Result := False; if (Prim and 1) = 0 then Exit; Z := Sqrt(Prim); Max := Trunc(Z) + 1; Divisor := 3; while Max > Divisor do begin if (Prim mod Divisor) = 0 then Exit; Inc(Divisor, 2); if (Prim mod Divisor) = 0 then Exit; Inc(Divisor, 4); end; Result := True; end;
procedure TForm1.Button1Click(Sender: TObject); begin IsPrime(StrToInt(Edit1.Text)); if Result = True then button1.caption:= 'ja' else button1.caption:= 'nein'; end; |
was ich in dem programm auch nicht verstehe, ist der befehl "trunc(z)".
da ich aber das komplette programm erklären muss, wäre es für mich eine grosse hilfe, wenn jemand, der ahnung davon hat, hinter jede zeile als kommentar schreiben könnte, was gerade in der zeile passiert.
das würde mich nämlich vor einer grossen blamage bewahren *gg*
gruss und danke schon mal im voraus und danke für alles vorige,
johannes
|
|
derDoc
      
Beiträge: 623
Win Vista Prof
D2007 Prof
|
Verfasst: Di 11.03.03 16:24
Benutz doch
Quelltext 1: 2: 3: 4: 5: 6: 7:
| procedure TForm1.Button1Click(Sender: TObject); begin if IsPrime(StrToInt(Edit1.Text)) = true then Button1.Caption := 'ja' else Button1.Caption := 'nein'; end; |
Das sollte gehen.
_________________ MfG derDoc
There are only 10 types of people: those who understand binary and those who don't.
|
|
sennaheu 
      
Beiträge: 22
|
Verfasst: Di 11.03.03 17:03
hey, prima, danke. jetzt funktioniert es.
ich bin jetzt mehrfach das programm durchgegangen und habe mich über befehle, die ich noch nicht kannte (zb. trunc) informiert.
allerdings verstehe ich nicht ganz, was dort mathematisch vor sich geht. wozu benötige ich die wurzel der zahl (variable z, die für max verwendet wird)? und was fange ich mit der max-zahl an?
ich brauche wirklich jemanden, der mir schritt für schritt erklären kann, was dort vor sich geht.
ist jemand zufällig aus der nähe von karlsruhe?
gruss,
johannes
|
|
Segelflieger
      
Beiträge: 124
WinXP Pro
D7 Prof
|
Verfasst: Di 11.03.03 17:09
Noch als Verständnishilfe für sennaheu:
'Result' ist eine vordefinierte LOKALE Variable, das heißt, sie ist in jeder procedure oder function eine eigene Variable (auch wenn sie überall den gleichen namen hat). Wenn du also in der procedure button1click nach Result fragst, ist das nicht das Result aus deiner Primzahlfunction.
Die Ergebnisse (Rückgabewerte) von functions erhält man, indem man die function einfach an der Stelle aufruft, wo man auch eine Variable mit dem Ergebnis hinschreiben könnte.
Beispiel:
Quelltext 1:
| Ergebnis := IrgendEineFunction(Parameter); |
Noch etwas zu dem 'Result': Innerhalb einer function muss man den Rückgabewert nicht unbedingt an 'Result' übergeben. Man kann ihn auch an den Namen der function übergeben (klingt seltsam, hier ist ein Bsp:)
Quelltext 1: 2: 3: 4: 5: 6:
| function IrgendEineFunction(Parameter...): Rückgabetyp; begin {irgendwelcher Code} ... IrgenEineFunction := Rückgabewert; end; |
aber natürlich ist es egal, ob man das nun so macht oder mit 'Result'. [/code]
_________________ Früher hatten die Menschen Angst vor der Zukunft. Heute muss die Zukunft Angst vor den Menschen haben.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 11.03.03 17:14
Und dass der Algorithmus nur bis zur Wurzel laufen muß, hat rein mathematische Gründe.
| Zitat: |
ist jemand zufällig aus der nähe von karlsruhe?
|
Soll jetzt noch jemand zu dir nach Hause kommen und es dir persönlich erklären? 
|
|
sennaheu 
      
Beiträge: 22
|
Verfasst: Di 11.03.03 17:18
nein, nein,
ist nur ob mir jemand allgemein helfen könnte. *gg*
*edit*
was sind das für mathematische gründe?
|
|
Segelflieger
      
Beiträge: 124
WinXP Pro
D7 Prof
|
Verfasst: Di 11.03.03 17:22
Die While-Schleife testet, ob eine Zahl (Divisor) ein Teiler der getesteten Zahl (Prim) ist. Dabei wird jeder Teiler von 3 bis MAX getestet (nicht jeder, es werden auch Zahlen übersprungen). MAX ergibt sich aus Z und Z aus der Wurzel von Prim, da der kleinste mögliche Teiler von Prim ja kleiner (oder gleich) als die Wurzel sein muss. Es wäre überflüssig, mit Zahlen rumzuprobieren, die größer als die Wurzel von Prim sind.
Bsp:
die Wurzel von 64 ist 8.
64 ist auch durch 16 teilbar, aber da 64/16 = 4 ist, ist diese Möglichkeit trotzdem abgecheckt ( 4 ist kleiner als  .
Hilft das irgendwie?
_________________ Früher hatten die Menschen Angst vor der Zukunft. Heute muss die Zukunft Angst vor den Menschen haben.
|
|
sennaheu 
      
Beiträge: 22
|
Verfasst: Di 11.03.03 17:23
danke,
jetzt müsst ich es morgen hinkriegen.
also, vielen dank nochmal an alle!!!
|
|
Segelflieger
      
Beiträge: 124
WinXP Pro
D7 Prof
|
Verfasst: Di 11.03.03 17:24
sollte heißen: 4 ist kleiner als 8
_________________ Früher hatten die Menschen Angst vor der Zukunft. Heute muss die Zukunft Angst vor den Menschen haben.
|
|
cosmo
Hält's aus hier
Beiträge: 2
|
Verfasst: Di 06.01.04 21:39
Hallo alle zusammen,
etwas Off-Topic aber habe ein Problem.
@Peter Lustig:
eine frage zum Miller-Rabin-Primzahl-Test.
und zwar habe ich den Algo. getestet und in C++ Portiert (bitte keine schläge weil ich hier mit C++ anfange). So und er geht auch wunderbar und sehr schnell "aber" möchte ich große Zahlen Testen wie zb.:
3203431780337 was eine Primzahl ist sagt er immer nein.
Kannst Du mir helfen das es auch für große Zahlen geht habe in C++ einen 64bit Datentyp alsosind von dieser Seite keine Probleme zu erwarten.
Über eine Antwort würde ich mich shr freuen.
|
|
Christian S.
      
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Di 06.01.04 22:58
Hallo!
Klar helfe ich Dir, das Ding unter C++ ans Laufen zu bekommen.  Am Besten schreibst Du mir mal 'ne PN mit Deinem Code!
MfG
Peter
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 481
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Mi 07.01.04 10:52
Zu dem Miller-Rabin-Test:
Tatsache ist, dass dieser Test recht gut ist, und auch bei SEHR großen Zahlen einigermaßen anwendbar ist. Und ich nehme an, dass der Java-Quellcode mal "korrigiert" worden ist, und nen Algorithmus von Java nach Delphi zu übersetzen sollte ja kein Problem sein...
ABER:
Wenn ich das richtig sehe, soll das ein Programm für die Schule werden. In der Schule fehlen meiner Meinung nach die mathematischen Grundlagen, um diesen Test zu verstehen. Und wenn dir schon nicht direkt klar wird, was es für "mathematische Gründe" hat, warum man beim normalen Test nur bis zur Wurzel der Zahl testet, naja.
Die Programmierbefehle sind nicht so schwer, sie bestehen ja fast nur aus mathematischen Berechnungen, aber warum diese Berechnungen zeigen, ob eine Zahl wahrscheinlich (!) eine Primzahl ist, sollte man auch verstehen.
Wenn du dich näher mit Primzahlen beschäftigen willst, mach da weiter und dringe tief in die Geheimnisse der Zahlentheorie ein. Aber wenn du nur deinen Lehrer beeindrucken willst, weil du was besonders tolles programmiert hast, dann würde ich es lassen. Denn erstens könnte dein Lehrer sagen: "Jetzt erklär mir doch mal bitte, warum das ein Primzahltest ist." oder aber zweitens: "Miller-Rabin? Nie gehört. Setzen, Sechs." In beiden Fällen hast du verloren 
_________________ We are, we were and will not be.
|
|
cosmo
Hält's aus hier
Beiträge: 2
|
Verfasst: Mi 07.01.04 11:18
@Gausi
Hi, meinst sennaheu der das Thema eröffnet hat oder mein frage??
Tschüß
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 481
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Mi 07.01.04 16:07
Uppps... da war ich wohl etwas vorschnell... Das Thema ist ja schon uralt, und der Ersteller hat die Aufgabe wohl schon längst vergessen...
Hab da zwei Personen gleichgesetzt, 'Tschuldigung für die Unaufmerksamkeit.
_________________ We are, we were and will not be.
|
|
|