Autor |
Beitrag |
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: So 21.08.05 16:55
Ich würde das noch so ändern
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: 51: 52: 53: 54: 55: 56:
| ... for k := 0 to MaxPrime div PrimeBits do begin FillChar(Primes[0], PrimeLen, 0); for i := 0 to Trunc(Sqrt((k + 1) * PrimeBits) / 30) do begin for j := 0 to 7 do begin if PrimesLUT[i] AND (1 shl j) = 0 then begin s := STEMPEL[j]; Num := i * 30 + s; if k = 0 then Num2 := Num * Num else Num2 := Trunc(k * PrimeBits / Num) * Num + Num;
mbit := Num2 mod 30; m := (Num2 - mbit) div 30 - k * PrimeLen; while m < PrimeLen do begin primes[m] := Primes[m] or MODS[mbit]; m := m + i; mbit := mbit + s; if mbit > 29 then begin mbit := mbit - 30; inc(m); end; end; end; end; end; end;
if not (FileName = '') then begin for k := 0 to MaxPrime div PrimeBits do begin for i := 0 to PrimeLen - 1 do begin for j := 0 to 7 do begin if k * PrimeBits + i * 30 + STEMPEL[j] > MaxPrime then Break; if not ((i = 0) AND (j = 0) AND (k = 0)) AND (Primes[i] AND (1 shl j) = 0) then SList.Add(IntToStr(k * PrimeBits + i * 30 + STEMPEL[j])); end; end; end;
SList.SaveToFile(FileName); SList.Free; end; end; |
So wird nicht jedesmal geprüft, ob FileName <> '' ist. (Hier verwende ich zu Testzwecken eine StringList. Ändert aber so nichts an der Funktion selber, sollte also nicht weiter stören.)
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
zemy
      
Beiträge: 207
Win XP Prof.
D7
|
Verfasst: So 21.08.05 17:16
Will ich mich auch mal einbringen  Sind zwar nur kleinigkeiten, aber vieleicht bringts ein paar Millisekunden.
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| mbit = Num2 mod 30 mbit = Num² mod 30 mbit = (30i + s)² mod 30 mbit = (900i² + 60is + s²) mod 30 [(a + km) mod m = a mod m] mbit = s² % 30 |
Und da kann man ja noch ein Array basteln, was die Werte für s² mod 30 speichert. Tada, ne Modulooperation gespart.
und jetzt noch so was..
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| m = (Num2 - mbit) div 30 m = (Num2 - s² mod 30) div 30 m = ( Num² - s² mod 30) div 30 m = ( (30i + s)² - s² mod 30) div 30 m = (900i² + 60is + s² - s² mod 30) div 30 m = 30i² + 2is + (s² - s² mod 30) div 30 |
Ob das jetzt günstiger ist, weiß ich nicht genau. (s² - s² mod 30) div 30 könnte man aber wieder in nen Array schreiben. Bleiben noch ein paar Multiplikationen und ne Addition. Ne Division wird vermieden.
Vieleicht bringts ja was.. ein paar Millisekunden
Mfg Zemy
Moderiert von AXMD: Code- durch Delphi-Tags ersetzt.
_________________ LifeIsToShortToThinkAboutTheShortness
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: So 21.08.05 17:20
Kannst du mal genauer sagen, was du da ändern willst? Denn % und ² gibts in Delphi nicht.
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
zemy
      
Beiträge: 207
Win XP Prof.
D7
|
Verfasst: So 21.08.05 17:42
Sollte blos Pseudocode werden
% entspricht mod und s² entspricht s*s...
_________________ LifeIsToShortToThinkAboutTheShortness
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: So 21.08.05 17:47
Deswegen versteh ich immer noch net was du willst... 
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
Phantom1
      
Beiträge: 390
|
Verfasst: So 21.08.05 18:19
Ich verstehe es schon, wolltes es früher schonmal probieren, bin aber nicht auf die formel gekommen und habs erstmal sein lassen.
Ich hab die mbitLUT (LookUpTable) mal eingebaut, geht leider nur in PrimesLUT-Schleife. Leider wurde der Code dadurch etwas langsamer, ich werd das mal genauer unter die Lupe nehmen.
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: So 21.08.05 21:21
Was stellen S, I, M und Num darstellen? Kannst Du deine Herleitung bitte mal etwas erläutern?
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Phantom1
      
Beiträge: 390
|
Verfasst: So 21.08.05 22:06
s,i,m,Num sind Variablen aus meinem Algorythmus.
Ich habe jetzt mal beide Vorschläge von Zemy eingebaut, bei 500mio zahlen dauerts jetzt nur noch 2,3 statt 2,55 sekunden.
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: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80:
| procedure SavePrimes(MaxPrime: Cardinal; const FileName: string = ''); const CACHE = 64*1024; STEMPEL: array[0..7] of Byte = (1, 7, 11, 13, 17, 19, 23, 29); MODS: array[0..29] of Byte = (0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 4, 0, 8, 0, 0, 0, 16, 0, 32, 0, 0, 0, 64, 0, 0, 0, 0, 0, 128); mBitLUT: array[0..7] of Byte = (1, 19, 1, 19, 19, 1, 19, 1); mLUT: array[0..7] of Byte = (0, 1, 4, 5, 9, 12, 17, 28); var Primes: array[0..CACHE-1] of Byte; PrimesLUT: array of Byte; i, j, k, PrimeLen, PrimeBits, Num, Num2, m, mbit, s: Cardinal; f: TextFile; begin if FileName<>'' then begin AssignFile(f, FileName); ReWrite(f); WriteLn(f, '2'+#13#10+'3'+#13#10+'5'); end;
SetLength(PrimesLUT, Trunc(Sqrt(MaxPrime)/30)); PrimesLUT[0]:=$01; PrimeLen:=Length(PrimesLUT); PrimeBits:=PrimeLen*30; for i:=0 to Trunc(Sqrt(PrimeBits)/30) do for j:=0 to 7 do if PrimesLUT[i] and (1 shl j)=0 then begin s:=STEMPEL[j]; mbit:=mBitLUT[j]; m:=30*(i*i) + 2*i*s + mLUT[j]; while m<PrimeLen do begin PrimesLUT[m]:=PrimesLUT[m] or MODS[mbit]; Inc(m, i); Inc(mbit, s); if mbit>29 then begin Dec(mbit, 30); Inc(m); end; end; end;
PrimeLen:=Length(Primes); PrimeBits:=PrimeLen*30; for k:=0 to MaxPrime div PrimeBits do begin FillChar(Primes[0], PrimeLen, 0); for i:=0 to Trunc(Sqrt((k+1)*PrimeBits)/30) do for j:=0 to 7 do if PrimesLUT[i] and (1 shl j)=0 then begin s:=STEMPEL[j]; if k=0 then begin mbit:=mbitLUT[j]; m:=30*(i*i) + 2*i*s + mLUT[j]; end else begin Num:=i*30+s; Num2:=Trunc(k*PrimeBits/Num)*Num+Num; mbit:=Num2 mod 30; m:=(Num2-mbit) div 30-k*PrimeLen; end; while m<PrimeLen do begin primes[m]:=Primes[m] or MODS[mbit]; Inc(m, i); Inc(mbit, s); if mbit>29 then begin Dec(mbit, 30); Inc(m); end; end; end; if FileName<>'' then for i:=0 To PrimeLen-1 do for j:=0 to 7 do begin if k*PrimeBits+i*30+STEMPEL[j]>MaxPrime then Break; if not ((i=0) and (j=0) and (k=0)) and (Primes[i] and (1 shl j)=0) then WriteLn(f, IntToStr(k*PrimeBits+i*30+STEMPEL[j])); end; end; if FileName<>'' then CloseFile(f); end; |
mfg
Phantom1
|
|
zemy
      
Beiträge: 207
Win XP Prof.
D7
|
Verfasst: Mo 22.08.05 00:32
cool.. 250ms. Hätte nicht gedacht, das es doch so viel bringt^^
_________________ LifeIsToShortToThinkAboutTheShortness
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mo 22.08.05 15:51
Da ich die Speicherfunktion rausgenommen habe aus der Schleife, ist nun auch das hier überflüssig:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| for j := 0 to 7 do begin if k * PrimeBits + i * 30 + STEMPEL[j] > MaxPrime then Break; if not ((i = 0) AND (j = 0) AND (k = 0)) AND (Primes[i] AND (1 shl j) = 0) then SList.Add(IntToStr(k * PrimeBits + i * 30 + STEMPEL[j])); end; |
-->
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7:
| for j := 1 to 7 do begin if k * PrimeBits + i * 30 + STEMPEL[j] > MaxPrime then Break; if not (Primes[i] AND (1 shl j) = 0) then SList.Add(IntToStr(k * PrimeBits + i * 30 + STEMPEL[j])); end; |
Sollte das Speichern vielleicht etwas verschnellern.
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
Phantom1
      
Beiträge: 390
|
Verfasst: Mo 22.08.05 18:17
@GTA-Place: was machst du denn da? das geht so nicht. Du kannst die Speicherfunktion nicht aus der Hauptschleife entfernen. Die berechneten Primzahlen stehen immer nur für einen durchgang zur verfügung, als einfaches Beispiel: Durchgang1 berechnet alle primzahlen von 1 bis 100 und Durchgang2 berechnet alle primzahlen von 101 bis 200. Bei jedem Durchgang wir der Speicher wieder auf 0 zurückgesetzt. Zudem rate ich von StringListen ab, die fressen nur unnötig viel speicher und sind zudem auch noch langsam.
|
|
zemy
      
Beiträge: 207
Win XP Prof.
D7
|
Verfasst: Mi 24.08.05 13:26
Wie währe es damit..
von
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| if FileName<>'' then for i:=0 To PrimeLen-1 do for j:=0 to 7 do begin if k*PrimeBits+i*30+STEMPEL[j]>MaxPrime then Break; if not ((i=0) and (j=0) and (k=0)) and (Primes[i] and (1 shl j)=0) then WriteLn(f, IntToStr(k*PrimeBits+i*30+STEMPEL[j])); end; end; |
in
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| if FileName<>'' then for i:=0 To PrimeLen-1 do for j:=0 to 7 do begin if k*PrimeBits+i*30+STEMPEL[j]>MaxPrime then Break; if (i or j or k or (Primes[i] and (1 shl j)) <> 0 then WriteLn(f, IntToStr(k*PrimeBits+i*30+STEMPEL[j])); end; end; |
_________________ LifeIsToShortToThinkAboutTheShortness
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mi 24.08.05 15:28
Mh... dann würde ich das irgendwie ändern, weil so wird ja jedesmal geprüft ob Filename <> '' ist und kostet minimal Zeit bei 500.000.000 Zahlen.
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mi 24.08.05 17:57
Bei den jetzigen Source-Schnipseln geht sowohl durch das WriteLn als auch durch das IntToStr wertvolle Zeit verloren, die man durch nutzen eines virtuellen dynamischen Arrays eingespart werden könnte:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| var PrimPtr: PInteger; PrimSize: Integer;
PrimPtr := VirtualAlloc(65536*1024);
if (i or j or k or (Primes[i] and (1 shl j)) <> 0 then Begin PrimPtr^ := k*PrimeBits+i*30+STEMPEL[j]; Inc(PrimPtr); end;
|
Damit sollte der Algo noch mal etwas schneller werden.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Phantom1
      
Beiträge: 390
|
Verfasst: Mi 24.08.05 21:11
zemy hat folgendes geschrieben: | Wie währe es damit..
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| if FileName<>'' then for i:=0 To PrimeLen-1 do for j:=0 to 7 do begin if k*PrimeBits+i*30+STEMPEL[j]>MaxPrime then Break; if (i or j or k or (Primes[i] and (1 shl j)) <> 0 then WriteLn(f, IntToStr(k*PrimeBits+i*30+STEMPEL[j])); end; end; | |
Geht so nicht, Primzahlen sind nur die Bits mit einer 0. Nebenbei: Die Sache mit der i,j,k überprüfung ist ja eigentlich nur weil sonst auch die Zahl 1 gespeichert werden würde, was aber kein Primzahl ist, daher diese Bedingung.
@GTA-Place: die Sache mit dem Filename<>"" kostet doch kaum Zeit, bzw kann man da auch nichts sinnvolles ändern. Dein Vorschlag mit dem not (Filename='') bringt keinen Unterschied.
@BenBE: wie gesagt wollte ich eigentlich die Speicherfunktion später verbessern... Ich hab mal den Speichervorgang beim schnellsten PrimzahlenProgramm das ich kenne getestet (ecprime). Das berechnen geht ja in ecprime wesentlich schneller als bei mir, aber das Speichern in ecprime ist verglichen mit meinen Code deutlich langsamer. Von daher kann doch meine Speicheralgo garnicht so langsam sein ^^
mfg
|
|
GTA-Place
      

Beiträge: 5248
Erhaltene Danke: 2
WIN XP, IE 7, FF 2.0
Delphi 7, Lazarus
|
Verfasst: Mi 24.08.05 21:18
Phantom1 hat folgendes geschrieben: | Dein Vorschlag mit dem not (Filename='') bringt keinen Unterschied. |
Das weiß ich auch, dass das nichts ändert. Hab aber in Errinerung mal gelesen zu haben, dass das besser als <> ist.
_________________ "Wer Ego-Shooter Killerspiele nennt, muss konsequenterweise jeden Horrorstreifen als Killerfilm bezeichnen." (Zeit.de)
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Do 25.08.05 15:31
Phantom1 hat folgendes geschrieben: | zemy hat folgendes geschrieben: | Wie währe es damit..
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| if FileName<>'' then for i:=0 To PrimeLen-1 do for j:=0 to 7 do begin if k*PrimeBits+i*30+STEMPEL[j]>MaxPrime then Break; if (i or j or k or (Primes[i] and (1 shl j)) <> 0 then WriteLn(f, IntToStr(k*PrimeBits+i*30+STEMPEL[j])); end; end; | |
|
Phantom1 hat folgendes geschrieben: | Geht so nicht, Primzahlen sind nur die Bits mit einer 0. Nebenbei: Die Sache mit der i,j,k überprüfung ist ja eigentlich nur weil sonst auch die Zahl 1 gespeichert werden würde, was aber kein Primzahl ist, daher diese Bedingung. |
Wenn diese Zeile nur zum filtern der Zahl eins verwendet wird könnte man durch k = 1 to ... sicherlich auch nochmal Zeit sparen, unter der Bedingung, dass man alle Primzahlen der ersten Reihe des Stempels voraussetzt und die Prüfung auf i or j or k <> 0 entfernt. Oder sehe ich da was falsch?
Phantom1 hat folgendes geschrieben: | @BenBE: wie gesagt wollte ich eigentlich die Speicherfunktion später verbessern... Ich hab mal den Speichervorgang beim schnellsten PrimzahlenProgramm das ich kenne getestet (ecprime). Das berechnen geht ja in ecprime wesentlich schneller als bei mir, aber das Speichern in ecprime ist verglichen mit meinen Code deutlich langsamer. Von daher kann doch meine Speicheralgo garnicht so langsam sein ^^ |
War ja auch nur eine Sache, die mir aufgefallen ist, wo noch relativ viel Potenzial drin stecken würde.
Naja, außerdem würd ich jegliche String-Operationen aus der Auswertungs-Prozedur entfernen; bremst nur unnötiger-Weise. Eine Binär-Speicherung reicht vollkommen aus ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
zemy
      
Beiträge: 207
Win XP Prof.
D7
|
Verfasst: Fr 26.08.05 13:04
Phantom1 hat folgendes geschrieben: | zemy hat folgendes geschrieben: | Wie währe es damit..
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| if FileName<>'' then for i:=0 To PrimeLen-1 do for j:=0 to 7 do begin if k*PrimeBits+i*30+STEMPEL[j]>MaxPrime then Break; if (i or j or k or (Primes[i] and (1 shl j)) <> 0 then WriteLn(f, IntToStr(k*PrimeBits+i*30+STEMPEL[j])); end; end; | |
Geht so nicht, Primzahlen sind nur die Bits mit einer 0. Nebenbei: Die Sache mit der i,j,k überprüfung ist ja eigentlich nur weil sonst auch die Zahl 1 gespeichert werden würde, was aber kein Primzahl ist, daher diese Bedingung.
@GTA-Place: die Sache mit dem Filename<>"" kostet doch kaum Zeit, bzw kann man da auch nichts sinnvolles ändern. Dein Vorschlag mit dem not (Filename='') bringt keinen Unterschied.
@BenBE: wie gesagt wollte ich eigentlich die Speicherfunktion später verbessern... Ich hab mal den Speichervorgang beim schnellsten PrimzahlenProgramm das ich kenne getestet (ecprime). Das berechnen geht ja in ecprime wesentlich schneller als bei mir, aber das Speichern in ecprime ist verglichen mit meinen Code deutlich langsamer. Von daher kann doch meine Speicheralgo garnicht so langsam sein ^^
mfg |
mit i or j or k werden die Zahlen doch einfach nur "geodert" (z.B. 11001 or 01101 = 11101) Mit Primes[i] and (1 shl j) generierst du auch nur ne Zahl. Die kann ja dann auch mit geodert werden. Aber nen Fehler habe ich trotzdem gemacht. Müsste heißen ...s[i] and (1 shl j)) = 0 then
_________________ LifeIsToShortToThinkAboutTheShortness
|
|
Phantom1
      
Beiträge: 390
|
Verfasst: Fr 26.08.05 13:47
zemy hat folgendes geschrieben: | mit i or j or k werden die Zahlen doch einfach nur "geodert" (z.B. 11001 or 01101 = 11101) Mit Primes[i] and (1 shl j) generierst du auch nur ne Zahl. Die kann ja dann auch mit geodert werden. Aber nen Fehler habe ich trotzdem gemacht. Müsste heißen ...s[i] and (1 shl j)) = 0 then |
Dein Code würde also so hier aussehen?:
Delphi-Quelltext 1:
| (i or j or k or (Primes[i] and (1 shl j)) = 0) |
In dem Fall wird nur die Zahl 1 gespeichert, alle anderem Primzahlen werden nicht gespeichert ^^
Die Bedingung wie ich sie gemacht habe, ist eigentlich schon optimal. Man könnte den ersten Durchgang (k=0) aus der schleife nehmen, aber dadurch wird nur der Code wesentlich länger, schneller wird es dadurch nicht.
|
|
Amateur
      
Beiträge: 777
(Win98, WinMe) WinXP Prof
D3 Prof, D6 Pers, D2k5 Pers., Turbo C++ Explorer
|
Verfasst: Fr 26.08.05 14:17
nur ma so weil ich auch nen eigenen algorithmus entwickeln will...
als was speichert ihr die zahlen wenn sie ziemlich groß werden? als integer geht ja irgendwann net mehr..
die größte primzahl is ja irgendwas mit 2^6000 -1 oder so...
sowas kann man ja gar net mehr als integervariable speichern...
welchen variablentyp nehmt ihr und bis zu welcher zahl geht der... oder kann man sowas irgendwie umgehn mit variant oder so?
_________________ "Kein dummes Gerede. Kein Rumrätseln. Denkt an nichts anderes mehr, nur noch an das, was vor euch liegt. Das ist die wahre Herausforderung. Ihr müßt euch vor euch selbst schützen, Leute." (Rennes in "Cube")
Beiträge: >700
|
|
|