2016-09-14 1 views
-4

Ich habe das untenstehende Programm geschrieben, um das Projekt Euler 12 zu lösen, welches die Suche nach der kleinsten Dreieckszahl mit über 500 Faktoren beinhaltet.Warum stürzt dieses Programm, das die kleinste Dreieckszahl mit> 500 Faktoren findet, ab?

Ich glaube nicht, dass es größere Fehler gibt. Ich vermute, Speicheroptimierung könnte ein Problem sein. Davon abgesehen, brauche ich jedoch das unsigned long long int für die große Dreieckszahl, die letztendlich die Antwort sein wird. Ich beginne meine natürliche Zahlenfolge bei triangleNumbers [0] = 10.000.000.000. Ich weiß, dass 9.000.000.000 ungefähr 300 Faktoren haben, also war 10.000.000.000 eine "beste Schätzung". Ich nehme jedoch an, dass 10.000.000.000 die "erste natürliche Zahl" ist und fügen fortlaufend weitere natürliche Zahlen hinzu, um die "zweite" natürliche Zahl und darüber hinaus zu erhalten (also triangleNumbers [1] = 10.000.000.000 + 2, triangleNumbers [2] = 10.000.000.000 +3 und so weiter).

Alle Vorschläge und Tipps würden geschätzt. Danke, dass du einem Anfänger geholfen hast.

#include <iostream> 
#include <vector> 
#include <math.h> 

using namespace std; 

bool keepRunning=true; 

unsigned long long int naturalNumberCount=0; 
unsigned long long int j=4; 
unsigned long long int sum=0; 

vector <unsigned long long int> triangleNumbers(0); 

unsigned long long int totalFactors=0; 
unsigned long long int trialDivisors=1; 

unsigned long long int storer=0; 

int main() 
{ 
    triangleNumbers[0]=10000000000; 
    triangleNumbers[1]=10000000002; 
    triangleNumbers[2]=10000000005; 
    triangleNumbers[3]=10000000009; 
    triangleNumbers[4]=10000000014; 
    //listed first few prime numbers above. j is set at 4 for this reason 

    naturalNumberCount=5; 
    //10000000014 is the 5th triangle number, and 5 is the 5th natural num 
    //need this for recursive relation 
    //5th triangle number = 4th triangle num + 5 (num + naturalNumberCount 

    while(keepRunning) 
    { 
     for(trialDivisors;trialDivisors<=(unsigned long long int)(sqrt(triangleNumbers[j]));trialDivisors++) 
     { 
      if(triangleNumbers[j]%trialDivisors==0) 
      { 
       totalFactors++; 
       if(totalFactors>499)//499 because the number itself will be a divisor of itself, so no need to check 
       { 
        keepRunning=false; 
        break; 
       } 
       else 
       { 
        keepRunning=true; 
       } 
      } 
      else 
      { 
       keepRunning=true; 
      } 
     } 
     //need the below to generate and store the next triangle number (as next element of array) 

     naturalNumberCount++;//for recursive relation 
     storer=triangleNumbers[j];//store the (j+1)'th triangle number, since we are changing j itself 
     j++;//raise j, we gonna add the next value 
     triangleNumbers[j]=(storer+naturalNumberCount);//the new value (last triangle number + current natural) 
     totalFactors=0;//reset total factors to preclude any carry-over 
    } 


    cout<<triangleNumbers[j]<<flush; 

    return 0; 
} 
+1

Also, als Sie es debuggten, wo fanden Sie, dass es abgestürzt ist? – John3136

+1

Hier ist ein Hinweis - Sie haben einen Vektor, der leer ist und Sie versuchen, auf Elemente in ihm zuzugreifen. – PaulMcKenzie

+0

Und inkrementieren j wird Vektor geht oit of sowieso gebunden .... – HazemGomaa

Antwort

0

TL;DR

#include <vector> 

std::vector <unsigned long long int> triangleNumbers(0); 

int main() 
{ 
    triangleNumbers[0]=10000000000; 
} 

Sie haben einen leeren Vektor, und die erste Zeile in main führt zu undefinierten Verhalten, da Sie versuchen, Artikel zuzugreifen 0 (es gibt kein solches Element).

Live Example using operator [ ]

Live Example showing what vector::at() does

Hinweis der zweite Link zeigt, dass Sie ein Element außerhalb der Grenzen durch die Verwendung at() statt [ ] den Zugriff auf das erste Element zugreifen.

Um Elemente in ein std::vector, fügt eine der Methoden konzipiert, dies zu tun, nämlich vector::push_back(), vector::insert(), vector::emplace_back(), vector::resize() oder die std::vector mit der erforderlichen Anzahl der Einträge konstruieren.

Der einfachste aus all diesen Möglichkeiten wäre, den Vektor mit der Initialisiererliste zu konstruieren:

std::vector<unsigned long long int> triangleNumbers = {10000000000, 10000000002, 10000000005, 10000000009, 10000000014};

std::vector reference

Sobald Sie richtig den Vektor einrichten, dann müssen Sie schauen im Rest Ihres Codes, um zu sehen, wo Sie möglicherweise auf einen Out-of-Bounds-Index zugreifen. Sehen Sie sich speziell j in Ihrer Schleife an und wie Sie es als Index verwenden. Die vector::at() Funktion teilt Ihnen sofort mit, wenn j die Grenzen überschreitet.


EDIT: Wenn Sie wirklich eine Syntax, die eine „Auto-erweitert“ Array würde simulieren, die nächstgelegene Sie kommen können dies wäre zu verwenden, um ein std::unordered_map<int, unsigned long long> wie gesehen von this example wollten.

Möglicherweise wäre die map Lösung ein Drop-In-Ersatz - Sie müssten es testen.

+0

Interessant. Ich habe fälschlicherweise geglaubt, dass ein Vektor bei Bedarf einfach dynamisch expandiert. Ich denke, ich brauche Push-Back. – Shehryar

+0

Sie können den 'Vektor' mit den ersten 5 Elementen initialisieren, wie meine Antwort zeigt. Allerdings müssen Sie definitiv "push_back" oder eine andere "Erweiterung" -Funktion verwenden, wenn Sie später Elemente hinzufügen möchten. – PaulMcKenzie

+0

@Shehryar Ich habe meine Antwort aktualisiert, um zu zeigen, dass eine naheliegende Entsprechung zu einer Simulation eines automatisch expandierten Vektors darin besteht, eine Karte eines bestimmten Typs zu verwenden. – PaulMcKenzie

Verwandte Themen