PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : C: floating exception



xzm
02-04-2008, 20:01
ich schon wieder...
diesmal versuch ich mich an dem project euler problem 3..
also hab ich erstmal versucht nen programm, das ein array erstellt, das für jede zahl bis LIMIT einen platz mit wert 0 bereitstellt zu schreiben, um anschließend die, die teilbar sind per 1 zu kennzeichnen, um so die primzahlen zu berechnen..
nunja, kann mir gut vorstellen, dass primzahlberechnung auch deutlich einfacher zu schreiben ist, dennoch würd es mich interessieren, warum das nicht läuft, denn obwohl der gcc mal wieder sauber durchläuft erhalte ich eine floating exception..
hier der code:

#include <stdio.h>
#include <stdlib.h>
#define LIMIT 10

int main() {
int i;
int j;
int k;
int l;
int prime[LIMIT];
for(i=2;i < LIMIT; i++) {
prime[i] = 0;
}
while(j < LIMIT) {
for(k=0; k < j; k++) {
if(j % prime[k] == 0) {
prime[k] = 1;
}
}
j++;
}
for(l=0; l < LIMIT && !(prime[l] == 1); l++) {
printf("%i is a primefactor of LIMIT!\n", prime[l]);
}
exit(0);
}


danke für die hilfe! :)

grüße!

ContainerDriver
02-04-2008, 20:55
Hallo,
zuerst mal initialisierst du j nicht. Der Fehler tritt dann in der Zeile


if(j % prime[k] == 0)

auf. prime[k] ist immer 0 und eine Division durch 0 ist nicht erlaubt.

Ich würde dir empfehlen, mal den gdb (GNU Debugger) anzuschauen. Wenn du dein Programm dann mit dem Schalter "-g" übersetzt (ich vermute du nimmst den gcc), dann werden Debugging-Informationen zu deinem Programm hinzugefügt. Mit


gdb ./programmname

und Eingabe von run kannst du dann den Debugger starten und bekommst gleich präsentiert, wo das Programm abstürzt.

Gruß, Florian

locus vivendi
02-04-2008, 22:29
#include <stdio.h>
#include <stdlib.h>
#define LIMIT 10

int main() {
int i;
int j;
int k;
int l;
int prime[LIMIT];
for(i=2;i < LIMIT; i++) {
prime[i] = 0;
}
while(j < LIMIT) {
for(k=0; k < j; k++) {
if(j % prime[k] == 0) {
prime[k] = 1;
}
}
j++;
}
for(l=0; l < LIMIT && !(prime[l] == 1); l++) {
printf("%i is a primefactor of LIMIT!\n", prime[l]);
}
exit(0);
}

Du darfst übrigens auch in C schon seit fast 10 Jahren die Deklarationen für Variablen dort vornehmen wo sie das erste Mal gebraucht werden, also nicht notwendigerweise am Anfang der Funktion. Ebenso darfst du statt einem Präprozessor Makro eine "const" deklarierte Variable verwenden um die Grenzen eines Arrays zu definieren. Diese Features sind in C ursprünglich nicht vorhanden gewesen, deshalb sieht man den ältern Stil gelegentlich noch immer. Aber seit die neuen Möglichkeiten von C++ auch in C übernommen wurden, sollte man sie durchaus nutzen. Alternativ kannst du natürlich auch gleich einen C++ Compiler zum Übersetzen benutzen (was allerdings unter Umständen auch geringfügige Änderungen am Code erfordern könnte).

ContainerDriver
02-04-2008, 22:47
Du darfst übrigens auch in C schon seit fast 10 Jahren die Deklarationen für Variablen dort vornehmen wo sie das erste Mal gebraucht werden, also nicht notwendigerweise am Anfang der Funktion.

Stimmt, das was ich oben geschrieben habe, ist also falsch. Das geht übrigens seit 1999 mit dem C-Standard C99.

BLUESCREEN3D
03-04-2008, 00:36
int i;
int j;
int k;
int l;
Hier hätten auch i und j gereicht (einfach i in mehreren Schleifen benutzen).



int prime[LIMIT];
for(i=2;i < LIMIT; i++) {
prime[i] = 0;
}
Ein ganzes Array mit 0 initialisieren geht so:

int prime[LIMIT] = { 0 };
Warnung: Wenn du folgendes schreibst, sind nicht alle Elemente 1: ... = { 1 };
Stattdessen ist das erste Element 1 und der Rest 0. (Rest wird immer auf 0 gesetzt bei dieser Initialisierungsart.)



if(j % prime[k] == 0) {
prime[k] = 1;
}
Hier ist auch ein logischer Fehler: Erstmal muss es j % k heißen, um zu sehen, ob j durch k teilbar ist und danach musst du auch prime[j] auf 1 setzen und nicht prime[k].



printf("%i is a primefactor of LIMIT!\n", prime[l]);
Noch ein logischer Fehler: Nicht jede Primzahl ist auch ein Primfaktor und du willst ja den größten Primfaktor und nicht die größte Primzahl finden ...
Aber schreib ruhig erstmal weiter ein Programm, dass Primzahlen findet und ausgibt - das ist auch eine gute Übung :D

xzm
04-04-2008, 07:33
Hier hätten auch i und j gereicht (einfach i in mehreren Schleifen benutzen).


Ein ganzes Array mit 0 initialisieren geht so:

int prime[LIMIT] = { 0 };
Warnung: Wenn du folgendes schreibst, sind nicht alle Elemente 1: ... = { 1 };
Stattdessen ist das erste Element 1 und der Rest 0. (Rest wird immer auf 0 gesetzt bei dieser Initialisierungsart.)


Hier ist auch ein logischer Fehler: Erstmal muss es j % k heißen, um zu sehen, ob j durch k teilbar ist und danach musst du auch prime[j] auf 1 setzen und nicht prime[k].


Noch ein logischer Fehler: Nicht jede Primzahl ist auch ein Primfaktor und du willst ja den größten Primfaktor und nicht die größte Primzahl finden ...
Aber schreib ruhig erstmal weiter ein Programm, dass Primzahlen findet und ausgibt - das ist auch eine gute Übung :D

danke für die ganze hilfe! werde mich die tage auf jedenfall mit dem gdb auseinandersetzen!

@Bluescreen: jo, das programm dient auch erstmal der übung da mir eh klar geworden ist, dass das nicht der richtige weg sein kann, denn bei LIMIT=10 kann das (wenn man keine log. fehler einbaut) ja so noch klappern, allerdings gehts ja beim project euler problem bis 600851475143, und daher wird es wohl schwierig werden ein array von prime[0] bis prime[600851475143] zu initialisieren.
wenn ich das programm mal sauber hinbekommen hab werd ich also umdenken müssen und nur die tatsächlichen primzahlen in ein array schreiben...
obwohls auch da schwierig wird, da ja der modulo operator (%) nur bei integer funktioniert? (stimmt das?) und 600851475143 wohl eher double benötigt ;)

grüße!

BLUESCREEN3D
04-04-2008, 13:22
obwohls auch da schwierig wird, da ja der modulo operator (%) nur bei integer funktioniert? (stimmt das?) und 600851475143 wohl eher double benötigt
Modulo mit double: Funktion fmod() aus math.h
Große Zahlen: Datentyp long long (ist 64 Bit lang).