Java Primzahlen

6 Antworten

Erstelle Dir zunächst die Function IsPrime(x).
(wie ceevee, ABER nicht bis x sondern bis sqrt(x)
und nicht Z++ sondern z+=2 für nur ungerade)
Nun durchsuchst Du alle ungeraden Vorgänger (x mod 2 >0)
und ohne 5 am Ende (x mod 5 >0)
Sobald IsPrime() true -> output

Test: Prime(50847534)=999999937
Prime(50847535)=10^9+7

mehr dazu unter http://www.gerdlamprecht.de/Primzahlen.htm

Im Internet gibt’s genug Online-Rechner, oder soll das eine Hausaufgabe sein?


martin7812  18.09.2013, 07:39

Für den Fall von z+=2 muss man aber überprüfen, ob die Zahl gerade ist und wenn ja, ob es sich um die Zahl 2 handelt.

Ansonsten wird jede gerade Zahl als Primzahl erkannt.

hypergerd  18.09.2013, 08:51
@martin7812

Nein! Das ist Teil der Optimierung:
- einmalig aus der Eingegebenen Zahl eine ungerade machen
- dann n-=2 und ohne Mod 5
- dann Aufruf IsPrim(), wobei mit 3 gestartet wird und intern z+=2!
So muss nur 1 mal statt n/2 mal auf UNGERADE überprüft werden.
Ich habe es noch weiter optimiert und statt z+=2 mit Array-Muster z+=a[i]
gearbeitet
Beispiel: n= 2 * 10^10 = 20000000000
Ergebnis: prime(882206716)=19999999967

ceevee  18.09.2013, 09:51
@hypergerd

Darf man sich auch irgendwo angucken, wie du das Array-Muster generierst?

ceevee  17.09.2013, 21:13

Genau so geht's wohl am besten, DH. Mein Sieb braucht bei 10^9 Zahlen insgesamt 953 MB, wenn man's ganz profimäßig mit einer Bitmaske macht, dann sinds nur noch um die 119 MB, Speicherplatz ist also bei heutigen Rechnern nicht mehr unbedingt das große Problem, allerdings kann man einige tausend Primzahlen mit diesem Algorithmus prüfen, bevor sich das Sieb rentiert.

Wenn du weißt, wie es geht, musst du es alleine hinkriegen.

Wenn du nicht weißt, wie es geht, musst du uns das konkrete Problem sagen, sonst können wir dir auch nicht helfen.


hallo794613 
Beitragsersteller
 17.09.2013, 12:20

ja, dann werde ich mal konkret! :)

Ich will eine Zahl X eingeben und dann will ich die nächst kleiner Primzahl. Als Beispiel X=10; Dann will ich das er mit 7 weiter rechnet und nicht mit allen Primzahlen die kleiner sind als 10, sondern nur mit der letzten Primzahl (7).

Da wäre es doch das klügste, wenn man bei 10 beginnt und ausrechnet ob sie einen teiler hat außer sich selbst und 1. Dann zur nächst kleiner Zahl 9 geht und wieder überprüft ob es sich um eine Prim handelt. Solange bis man halt dann zur nächsten Primzahl kommt.

Aber wie man das in Java macht weiß ich nicht :X und da bitte ich dich sehr um hilfe!

ceevee  17.09.2013, 12:58
@hallo794613

Teil dir die Aufgabe auf - kriegst du schon ein Eratosthenes-Sieb zusammen? Also ein Array oder eine Liste, wo jeweils angegeben ist, ob der Index eine Primzahl ist? (sieb[1] = false, sieb[2] = true, sieb[3] = true, sieb[4] = false, sieb[5] = true, sieb[6] = false....)

hallo794613 
Beitragsersteller
 17.09.2013, 13:10
@ceevee

nein ich habe nur eine liste, wo alle primzahlen drin sind von 1 bis n;

aber da würde ein computer doch ewig brauchen darum mein vorschlag,

Da wäre es doch das klügste, wenn man bei z.b. 10 beginnt und ausrechnet ob sie einen teiler hat außer sich selbst und 1. Dann zur nächst kleiner Zahl 9 geht und wieder überprüft ob es sich um eine Prim handelt. Solange bis man halt dann zur nächsten Primzahl kommt.

weil ich habe zum teil zahlen, wie 7358 und dann von 2 anfangen zu rechnen macht doch kein sinn, wenn ich die nächst kleinere Primzahl suche.

darum meinte ich 7358 - 1 und damit halt ausrechnet ob die eine Primzahl ist? Das dann in einer Schleife solange bis er eine gefunden hat die maximal nur 2 teiler hat, weil alle geraden zahlen fallen ja prinzipiell sowieso weg :)

Oder habe ich da einen Denkfehler?

Dankeschön schonmal für die schnelle und gute hilfe :)

ceevee  17.09.2013, 13:37
@hallo794613

darum meinte ich 7358 - 1 und damit halt ausrechnet ob die eine Primzahl ist? Das dann in einer Schleife solange bis er eine gefunden hat die maximal nur 2 teiler hat, weil alle geraden zahlen fallen ja prinzipiell sowieso weg :)

Das wäre der simple (und langsame) Ansatz, der würde ungefähr so aussehen.

// x = zu pruefende Zahl
bool isPrim = true;
for(int z=2;z<x;z++)
{
      if(x % z == 0) //% = Modulo - Es wird der Rest der Ganzzahldivision zurückgegeben, 10 % 3 = 1
      {
          isprim = false;
          break;
      }
}
return isprim;

Der Ansatz des Primsiebes ist eigentlich genau umgekehrt, du generierst dir vor deinem eigentlichen Programm das Sieb und hälst es während des Ablaufs im Speicher. Hier wäre der Code dafür: http://introcs.cs.princeton.edu/java/14array/PrimeSieve.java.html (Versuch unbedingt zu verstehen, was da gemacht wird!). Dort kannst du dann komfortabel das Array abfragen, eben beispielsweise isPrime[7357] und bekommst dann "true" oder "false" zurück. Wenn du die nächstniedrigere Primzahl von einer gegebenen Zahl suchst, dann musst du eben von deiner gegebenen Zahl herunterzählen, bis der Wert "true" wird.

Franz1957  17.09.2013, 14:07
@hallo794613

Oder habe ich da einen Denkfehler?

Es macht schon Sinn, mit 2 zu rechnen anzufangen. Um die neben 7358 nächstkleinere Primzahl zu erkennen, mußt Du ja alle x-Werte: 7358, 7357, 7356, 7355, 7354, 7353 usw. nacheinander testen. Dazu mußt Du prüfen, ob sie außer 1 und sich selbst Teiler haben und dazu mußt Du immer die möglichen Teiler der Reihe nach ausprobieren. Um das zeitsparend zu tun, solltest Du:

  • Erstens nur die Primzahlen zwischen 2 und Wurzel aus x als Teiler ausprobieren. (Existiert kein Teiler bis maximal zur Wurzel, dann gibt es oberhalb der Wurzel auch keinen.)
  • Zweitens mit den kleinen Teilerkandidaten beginnen, also mit 2, 3, 5, 7 usw. Denn die kleineren sind mit größerer Wahrscheinlichkeit als die großen tatsächlich Teiler und je schneller das Programm einen Teiler gefunden hat, um so schneller kann es zum nächsten x weitergehen.

Berechne also in einem vorbereitenden Arbeitsschritt mit dem Sieb des Eratosthenes eine Tabelle aller Primzahlen bis zur Wurzel des größten x-Wertes, mit dem Du arbeiten willst. Teste dann bei jedem x, mit 2 beginnend bis zur Wurzel aus x, die Primzahlen durch, ob sie x teilen, und geh, sobald ein Teiler gefunden ist, zum nächstkleineren x weiter. Tu das so lange, bis ein x gefunden ist, das keinen Teiler hat. Das ist dann die gesuchte Primzahl.

hallo794613 
Beitragsersteller
 17.09.2013, 14:52
@ceevee

Moment, willst du damit sagen, dass ich alle primzahlen vor ab generieren soll und die dann im speicher halte?

Das programm generiert ja prinzipiell schonmal alle primzahlen

http://de.wikibooks.org/wiki/Primzahlen:_Programmbeispiele#Java

und du meinst ich soll die zwischenspeichern später dann abfragen? Vielleicht kannst du ja noch ein paar worte mehr zu deiner idee und dem skript verlieren, damit ich das besser nachvollziehen kann, vielen dank schonmal bis dahin!!! :)

hallo794613 
Beitragsersteller
 17.09.2013, 14:58
@Franz1957

ja gut dann verwerfe ich den gedanken und beginne lieber bei 2, berrechne alle prim bis zu meinem limit x und checke rückwirkend ab, welche die nächst gelegene primzahl ist?

http://de.wikibooks.org/wiki/Primzahlen:_Programmbeispiele#Java

über dieses script werden ja schonmal alle primzahlen errechnet, wie schaffe ich es dann, das er rückwirkend die nächst kleinere mir ausgibt? :)

auch dir ein riesen dankeschön bis dahin! :)

hypergerd  17.09.2013, 15:31
@ceevee

Sieb beginnt von UNTEN und ein Array von über 1 Mrd. im Speicher zu halten ist nicht nur teuer, sondern ineffektiv.

procoder42  17.09.2013, 17:07
@ceevee

ich würde nen ähnlichen ansatzt wie ceevee wählen.
nur das ich die hälfte oberhalb von x und die unterhalb von x nach primzahlen durchforsten (leichte abänderung von ceevees code) und die beiden Resultate (erste Primzahl) vergleichen (welche ist näher dran?)

procoder42  17.09.2013, 17:51
@hallo794613

:o das wäre sehr blöd, die nächste primzahl so zu errechnen. die nächste primzahl könnte ja auch über x liegen. außerdem verbrauchst du unnötig rechenzeit und machst alles viel zu kompliziert

procoder42  17.09.2013, 17:56
@ceevee

und was ist da dann der unterschied zur hashmap ??? oder wird der boolean dazu automatisch generiert ?

hallo794613 
Beitragsersteller
 18.09.2013, 12:42
@procoder42

Ja das kann sein aber ich will ja eh nur unter x haben, aber du hast recht mit der rechenzeit bei 30k abwärts dauert das schon ein gaaaaanzes stück!

Auf der Wikipedia-Seite des Eratosthenes-Siebes gibt's den Code als Pseudocode, auf dieser Seite sind auch einige Optimierungen erklärt. Den Vorgang, diesen Pseudocode in Java zu übersetzen, bezeichnet man auch als "programmieren", das kann dir keiner abnehmen. Und dann musst du nur noch gucken, welchen Wert deine Zahl im Sieb hat.

du überprüfst einfach um x herum (vielleicht 100 zahlen) ob die momentane zahl eine primzahl ist . dann vergleichst du die ergebnisse auf beiden Seiten


procoder42  17.09.2013, 17:54

if(x-1 >= 1){ return;
while(isprim == false){ // primzahlprüfung
}
//nachdem die primzahl ermittelt wurde
if(primoberhalb >= primunterhalb){
return primoberhalb; }
else {
return prim
unterhalb;
}


hallo794613 
Beitragsersteller
 17.09.2013, 11:11

Der mann ist gut!

Ich habe nur rotz dazu gefunden -.-

Danke für die Hilfe!! :)

ceevee  17.09.2013, 12:02
@hallo794613

Das Programmbeispiel ist aber auch Rotz... der Primzahltester ist (gerade für große Zahlen) ziemlich ineffizient.

hallo794613 
Beitragsersteller
 17.09.2013, 12:41
@ceevee

ist mir auch aufgefallen, nach 30k wirds echt ätzend

HolderEDII  17.09.2013, 12:59
@hallo794613

Oje, Die Routine braucht nicht bei 1 starten, sondern kann ab einer beliebigen Zahl gestartet werden, sie wird dann effizienter!
Voraussetzung ist das Streichen in einem Array.
https://de.wikipedia.org/wiki/Sieb_des_Eratosthenes
Lege ein 1000er Array an und streiche darin die Zahlen wie Wiki es zeigt!
Ich hab sie schon mal selbst gebraucht, aber frag bitte nicht, wo ich das Ding jetzt habe!

hallo794613 
Beitragsersteller
 17.09.2013, 13:23
@HolderEDII

mein problem ist doch ein ganz anderes,

ich habe eine zahl x und will die nächst kleinere primzahl davon haben wie bewerkstellige ich das in java?

hypergerd  17.09.2013, 13:44
@HolderEDII

Achtung Virus!!! Seite hat zwar einiges über Prime... aber zig ActiveX , Cookies und Virenseiten im Hintergrund!!! Nur mit Browser ansehen, wo alles abgeschaltet ist!

ceevee  17.09.2013, 13:55
@HolderEDII

softuses ist allgemein doof, weil die alles automatisiert auf deutsch übersetzen und man kaum versteht, was die da eigentlich schreiben.

HolderEDII  17.09.2013, 15:46
@hallo794613

public class Primzahl {

public static void main(String[] args) {
    boolean gefunden=false;
    int limit = 100000000;
    int i;
    int zahl;                                                       // Zu überprüfende Zahl
    int zaehler;                                                    // Durch diese Zahl soll geteilt werden
    int teiler;                                                     // Anzahl der möglichen Teiler
    int zahl2;                                                      // Rest bei der Division


    zahl = limit-1;
    do
    {
        if (zahl == 1) // Ausschluss der Zahl 1 als Primzahl
        {
            System.out.println("");
        } else {
            teiler = 0;
            for (zaehler = 1; zaehler <= zahl; zaehler++) // Es empfiehlt sich den Terminationswert auf zahl zu 
            //setzen und nicht auf limit, da die Berechnung von Primzahlen 
            //bis zu Milliardenbeträgen sonst nur äußerst langsam 
            //funktioniert. Die Teilung durch Zahlen, die größer sind als 
            //die zu überprüfende Zahl selbst ist ohne hin obsolet.
            {
                zahl2 = zahl % zaehler;                 // Division der Ausgangszahl durch eine weitere und ablegen des Rests in der Variabel zahl2
                if (zahl2 == 0) // Falls der Rest gleich 0 ist ist ein Teiler gefunden
                {
                    teiler++;
                }


            }
            if (teiler == 2) // Wenn die Zahl genau 2 Teiler hat ist sie eine Primzahl
            {
                gefunden=true;
                System.out.println(zahl + " ist eine Primzahl, da sie genau " + teiler + " Teiler hat");
            }
            /*else                                          // Andernfalls ist sie keine Primzahl
             System.out.println(zahl+" ist KEINE Primzahl");*/
        }
        zahl--;
    }while (!gefunden);

}

}

So, das Sieb des Erastotenes, du kannst sie als Test nach Suboptimierers tendenziöser Prüfung laufen lassen.