Autor Beitrag
luckyluc
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 103



BeitragVerfasst: Di 13.01.09 16:13 
Hallo
ich habe ein Programm welches wenn man eine Zahl eingibt, bis zu dieser Zahl alle Primzahlen ausgibt.
Nun nöchte ich diese Programm optimierend.h so gestalten dass das programm die primzahlen noch schneller findet. außer dass man nur bis zur wurzel der zu prüfenden zahl, den teiler hochzählen muss fällt mir nicht anderes ein.
Vielleicht habt ihr noch eine Idee?
Hier folgen zwei Quellcodes (sind im Grunde genommen das gleich, die for schleife ist jedoch schneller als die repeat)

1)
ausblenden volle Höhe Delphi-Quelltext
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:
var
  Form1: TForm1;
  i,teiler, eing_zahl,zeile: Integer;
  primzahl: Boolean;
  
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
zeile:= 0;
eing_zahl:= StrToInt (Edit1.Text);


for i := 4 to eing_zahl do
begin
  primzahl := true;

  for teiler := 2 to Trunc(sqrt(i)) do
   if i mod teiler = 0 then primzahl:= false; 

   if primzahl = true then
   begin
   inc (zeile);
    StringGrid1.Cells[0,zeile] := IntToStr(i);
    StringGrid1.RowCount := StringGrid1.RowCount+1;
    end;

end;//for
end;


2)
ausblenden volle Höhe Delphi-Quelltext
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:
var
  Form1: TForm1;
  i,teiler, eing_zahl,zeile: Integer;
  primzahl: Boolean;
  


implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
zeile:= 0;
eing_zahl:= StrToInt (Edit1.Text);

for i := 4 to eing_zahl do
begin
  primzahl := true;

 
   teiler:= 2;
   repeat
   if i mod teiler = 0 then primzahl := false;
   inc (teiler);
   until teiler = i-1;

   if primzahl = true then
   begin
   inc (zeile);
    StringGrid1.Cells[0,zeile] := IntToStr(i);
    StringGrid1.RowCount := StringGrid1.RowCount+1;
    end;

end;//for
end;



Danke !


Moderiert von user profile iconNarses: Topic aus Sonstiges (Delphi) verschoben am Di 13.01.2009 um 15:16
Nersgatt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1581
Erhaltene Danke: 279


Delphi 10 Seattle Prof.
BeitragVerfasst: Di 13.01.09 16:47 
Schau mal hier:
de.wikipedia.org/wiki/Primzahltest
Du hast bisher die Probedivision umgesetzt.

_________________
Gruß, Jens
Zuerst ignorieren sie dich, dann lachen sie über dich, dann bekämpfen sie dich und dann gewinnst du. (Mahatma Gandhi)
Jelly
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Di 13.01.09 16:52 
Merke dir jede gefundene Primzahl in einem Array, und prüfe alle weiteren Zahlen nur auf Divisionen durch bereits gefundene Primzahlen.

Bsp: Du hast 2, 3, 5, 7, 11, 13 bereits gefunden
Du testest gern 143
Nimm die Wurzel: = 11,96... Prüfe als Division aller Primzahlen bis 12. d.h. es reicht aus eine Test durch 2, 3, 5, 7, 11 und 13 durchzuführen.

Ergibt eine der Divisionen 0, so ist die Zahl 143 KEINE Primzahl.

Ausserdem: Es hilft die Schleife abzubrechen, wenn einmal eine Division 0 ergibt. Du durchläufst das Testen jedoch noch weiter. Breche ab und teste die nächste Zahl.

Ums noch schneller zu machen. Vor vorneweg ist schon mal jede 2. Zahl keine Primzahl. Also alle geraden Zahlen brauchst du erst gar nicht testen (ausser 2).
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Di 13.01.09 17:28 
user profile iconJelly hat folgendes geschrieben Zum zitierten Posting springen:
Merke dir jede gefundene Primzahl in einem Array, und prüfe alle weiteren Zahlen nur auf Divisionen durch bereits gefundene Primzahlen.

Bsp: Du hast 2, 3, 5, 7, 11, 13 bereits gefunden
Du testest gern 143
Nimm die Wurzel: = 11,96... Prüfe als Division aller Primzahlen bis 12. d.h. es reicht aus eine Test durch 2, 3, 5, 7, 11 und 13 durchzuführen.

Ergibt eine der Divisionen 0, so ist die Zahl 143 KEINE Primzahl.

Ausserdem: Es hilft die Schleife abzubrechen, wenn einmal eine Division 0 ergibt. Du durchläufst das Testen jedoch noch weiter. Breche ab und teste die nächste Zahl.

Ums noch schneller zu machen. Vor vorneweg ist schon mal jede 2. Zahl keine Primzahl. Also alle geraden Zahlen brauchst du erst gar nicht testen (ausser 2).

So ähnlich funktioniert das Sieb des Eratosthenes ;)
ausblenden volle Höhe Delphi-Quelltext
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:
var 
  Form1: TForm1; 
  
implementation 


{$R *.dfm} 

procedure TForm1.Button1Click(Sender: TObject); 
var
  eing_zahl, zahl, i, limit: Integer; 
  zahlen: Array of Boolean; 
begin 

eing_zahl:= StrToInt (Edit1.Text); 

limit := Trunc(sqrt(eing_zahl))

setlength(zahlen, eing_zahl + 1);

zahlen[0] := false;
zahlen[1] := false; // 0 & 1 per Def. nicht prim
zahlen[2] := true; // 2 per Def. prim

for i := 3 to eing_zahl do 
  zahlen[i] := (i mod 2) = 1;

zahl := 2;

while zahl <= limit do
begin
   inc(zahl);

   if not zahlen[zahl] then // Wenn keine Primzahl überspringen
      continue;

   i := zahl * 2;
   while i <= eing_zahl do
   begin
     zahlen[i] := false; // Vielfache einer Primzahlen sind nicht prim
     i := i + zahl;
   end;
end

for i := 3 to eing_zahl do 
  if zahlen[i] then
    Memo1.Lines.Add(inttostr(i) + ' ist prim!');

end;


Am Ende ist zahlen[x] wahr für jede Primzahl und falsch für jede nicht-Primzahl im Bereich ;)
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Di 13.01.09 18:21 
Hallo,

Gab es hier alles schon, sind aber viele Beiträge :
www.delphi-forum.de/...t=contest+primzahlen

Gruß Horst
platzwart
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1054
Erhaltene Danke: 78

Win 7, Ubuntu 9.10
Delphi 2007 Pro, C++, Qt
BeitragVerfasst: Di 13.01.09 20:32 
Primzahlen (>3) sind immer in der Form von 6n+/-1

_________________
Wissenschaft schafft Wissenschaft, denn Wissenschaft ist Wissenschaft, die mit Wissen und Schaffen Wissen schafft. (myself)
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Di 13.01.09 21:44 
Wirklich? Ist das bewiesen?
Hidden
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2242
Erhaltene Danke: 55

Win10
VS Code, Delphi 2010 Prof.
BeitragVerfasst: Di 13.01.09 21:52 
Hi :)

Wenn du zu 6n 3 addierst/subtrahierst, kommst du auf eine durch drei teilbare zahl => nicht prim

+- 2 => durch 2 teilbar

und noch +-0 => durch 3 und 2. Es verbleiben also nurnoch +-1.

aber diese Einschränkung kann man doch beliebig weiterspinnen, indem man stets die Vielfachen de nächsten Primzahl wegnimmt ;) . Die Formel hier liefert ja einfach nur alle Zahlen, die weder durch 3, noch durch 2 teilbar sind.

mfG,

_________________
Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
JayEff
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2971

Windows Vista Ultimate
D7 Enterprise
BeitragVerfasst: Mi 14.01.09 00:23 
user profile iconBoldar hat folgendes geschrieben Zum zitierten Posting springen:
Wirklich? Ist das bewiesen?
Leicht zu beweisen:
Ein Freund von mir hat folgendes geschrieben:
Also - überleg erstmal - sei p > 3 eine Primzahl. Kann sie dann gerade sein? - Natürlich nicht.
Jede ganze Zahl ist von der Form 6x + i (wobei i die Werte -1,0,1,2,3,4 durchläuft)
Als Primzahl kann sie nicht von der Form 6x + 0, 6x + 2, 6x + 4 sein, denn dann wäre sie durch zwei teilbar.
Wäre sie von der Form 6x + 3 = 3(2x + 1), dann wäre sie durch 3 teilbar.
Bleibt also nur 1 und -1 übrig.
:zustimm:

_________________
>+++[>+++[>++++++++<-]<-]<++++[>++++[>>>+++++++<<<-]<-]<<++
[>++[>++[>>++++<<-]<-]<-]>>>>>++++++++++++++++++.+++++++.>++.-.<<.>>--.<+++++..<+.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 14.01.09 00:25 
Moin!

Bitte ändere den Titel des Topics, da er wenig über das eigentlich Thema verrät. Hier der entsprechende Absatz aus den Richtlinien:

1.2 Beiträge:
Bitte formuliere den Betreff Deiner Beiträge so, dass andere Mitglieder anhand dieser bereits das eigentliche Thema festmachen können. Beiträge wie etwa "Eine Anfängerfrage" oder "Weiß jemand, wie das geht?" lassen den Leser im Unklaren darüber, was das Thema der Diskussion ist.[...]

Einfach oben bei Deinem ersten Beitrag auf user defined image oder user defined image klicken und den Titel ändern. Danke Dir!

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Horst_H
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1654
Erhaltene Danke: 244

WIN10,PuppyLinux
FreePascal,Lazarus
BeitragVerfasst: Mi 14.01.09 02:17 
Hallo,

heute habe mal eine Uraltversoin von Anfang 2001 ausgegraben:
wheel-sieving (Bei www.devalco.de Stempel-Verfahren ).
Ein Stempel der Länge 2x3x5 = 30 (=5# wie 5! nur mit den ersten Primzahlen bis 5 ) hat nur noch (2-1)x(3-1)x(5-1) = 8 Erhebungen(beim Rad Zähne)[1,7,11,13,17,19,23,29] [31,37,..59] , was die Zahlen, die teilerfremd zu 2,3,5 sind darstellt.
Man hat jetzt nur noch 8/30 = 0.2666 aller Zahlen zu betrachten, weil die anderen garantiert durch 2,3,5 teilbar sind.
Jetzt braucht man nur 8 Bit um die 30 abzubilden muss aber eine Umrechnung vornehmen um aus der Zahl die Position im Bitfeld zu bestimmen und umgekehrt, welche Zahl repräsentiert ein bestimmtes gesetztes Bit.

Das kann man nicht nur 2,3,5 , sondern allgemein machen. ( Das gab eine paar neue Knoten im Hirn )
Jetzt braucht man in diesem Zahlenkreis beim Ausstreichen aber auch nur ab dem Quadrat nur die ausstreichen die auch vorkommen können.

Beispiel 7 ausstreichen: 7x [7,11,13,17,19... man muss also nur noch 8/30 Zahlen ausstreichen, statt vorher 7x[7,8,9,10,11,12,..

Man kann dies aber genauso für alle Zahlen die Teilerfremd zu den ersten 5 Primzahlen 2,3,5,7,11 sind machen.
Und das kann mein Programm, keine Sorge es wird dadurch nicht viel schneller ;-) weil der Aufwand recht schnell sehr groß wird.

Anbei das Negativbeispiel BIS = 6 ( = 17#) dauert doppelt solange wie BIS= 5 = 13# bei 1e9 , welches bei mir das schnellste bei diesem Verfahren ist. Beide belegen etwa 26 Mb.
Einmal 23,?? das andere Mal 11,8 Sekunden für die Zahlen eins bis eine Milliarde (2.3 Ghz,Amd X2)

Gruß Horst
Edit:
A space-efficient fast prime number sieve (1996) als pdf:
citeseerx.ist.psu.ed...ep=rep1&type=pdf
Meine Version ist scheinbar New_SW
Aber dort citeseerx.ist.psu.ed...=Search&sort=rel
findest Du auch richtig schnelle quadratische Siebe , wie das von alzaimar genutzte aus primegen.Siehe auch unten auf www.primzahlen.de/fi...referent/kw/sieb.htm
Einloggen, um Attachments anzusehen!


Zuletzt bearbeitet von Horst_H am Mi 14.01.09 15:04, insgesamt 1-mal bearbeitet
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4798
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 14.01.09 11:35 
Es gibt noch einen möglichen Pre-Check:
ausblenden Quelltext
1:
2:
3:
4:
if((n * n) % 24 == 1) // wenn man die Schleife bei 5 beginnen läßt (2 und 3 sind ja eh bekannt!)
{

}

Dieser verkürzt die Primzahlsuche nochmals. Man muß nur zusehen, daß (n * n) nicht größer als der maximale Wertebereich der Variablen wird (d.h. am besten int64 benutzen).

Hier mal mein kompletter Code in C++:
ausblenden Quelltext
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:
void PrintPrims(ostream &os, unsigned int nMaxPrim)
{
  os << "2, 3";

  for(unsigned int n=5; n<=nMaxPrim; n+=2)
  {
    unsigned __int64 n2 = n; // avoid overflow
    if((n2 * n2) % 24 == 1) // pre-check for prim
    {
      unsigned int nMax = sqrt(n);
      bool bPrim = true;

      for(unsigned int m=3; m<=nMax; m+=2)
        if(n % m == 0)
        {
          bPrim = false;
          break;
        }

      if(bPrim)
        os << ", " << n;
    }
  }

  os << endl;
}

wobei sqrt(unsignd int) selbst implementiert ist (keine Fließkommazahlenberechnung, sondern mittels Intervallverfahren).

Die Liste der Primzahlen bis 1 Mio. füge ich mal an (ca. 600KB).

Moderiert von user profile iconNarses: Anhang gezippt
Einloggen, um Attachments anzusehen!