Perfekte Zahlen berechnen

Hallo!

Code:
#include <stdio.h>

int main(int argc, char* argv[]){
	printf("Geben Sie bitte eine Zahl ein bis zu der alle perfekten \nZahlen errechnet werden sollen: ");
	int zahl = 0,erg = 0;
	scanf("%d",&zahl);

	if(zahl <= 0){
		return 0;
	}
	
	int j = 1;

	for(; j <= zahl;++j){
	   int summe = 0;
	   int i = 1;
	   for(; i < j; ++i){
		   summe += (((j%i) == 0) ? i : 0);
	   }
	   if(summe == j){
	      printf("Zahl: %d ist perfekt!\n",j);
	   }
	}

	return 0;
}

Das lauft nun sauber durch bei DevCpp im C Modus:
Compiler: Default compiler
Building Makefile: "C:\Dev-Cpp\test1\Makefile.win"
Executing make...
make.exe -f "C:\Dev-Cpp\test1\Makefile.win" all
gcc.exe main.o -o "test1.exe" -L"C:/Dev-Cpp/lib"

Execution terminated
Compilation successful

@Redwing bei mir bringt die Änderung kein Ergebnis mehr...
außerdem sollte man sich Optimierungen zum leichteren Verständnis erstmal sparen.

Gruß Tom
 
Hab ich auch grad gemerkt...
Bei meinem obigen Beispiel lief es.
Hier nochmal der etwas abgeänderte
optimierte Code:

Wenn du ihn so nimmst wie er ist sollte es laufen:

Code:
#include <stdio.h>

int main(int argc, char* argv[]){ 
        printf("Geben Sie bitte eine Zahl ein bis zu der alle perfekten \nZahlen errechnet werden sollen: ");
        int zahl,erg = 0,i = 1, j = 2;
        scanf("%d",&zahl);

        if(zahl <= 0){
                return 0;
        }

        for(j = zahl; j > 1;j--){
           int summe = 1;
           for(i = 2; i*i < j; i++){
                   if(j % i == 0)
                        summe = summe + i + j/i;
           }
           if(summe == j){
              printf("Zahl: %d ist perfekt!\n",j);
           }
        }

        return 0;
}
 
@thomas:
Code:
error C2143: Syntaxfehler : Fehlendes ';' vor 'type'
error C2065: 'zahl' : nichtdeklarierter Bezeichner
error C2143: Syntaxfehler : Fehlendes ';' vor 'type'
error C2065: 'j' : nichtdeklarierter Bezeichner



test.obj - 4 Fehler, 0 Warnung(en)
 
Dann versuchs mal so:
Code:
#include <stdio.h>

int main(int argc, char* argv[]){
	printf("Geben Sie bitte eine Zahl ein bis zu der alle perfekten\nZahlen errechnet werden sollen: ");
	int zahl = 0;
    int erg = 0;
	scanf("%d",&zahl);

	if(zahl <= 0){
		return 0;
	}
	
	int j = 1;

	for(; j <= zahl;++j){
	   int summe = 0;
	   int i = 1;
	   for(; i < j; ++i){
		   summe += (((j%i) == 0) ? i : 0);
	   }
	   if(summe == j){
	      printf("Zahl: %d ist perfekt!\n",j);
	   }
	}
	return 0;
}

Was für einen pingeligen Compiler verwendest du denn?

Gruß Tom
 
visual studio 6

der code von redwing hat funktioniert. danke dir und auch dir thomas.

zum verständis würde ich gerne diese schritte auch verstehen

Code:
for(j = zahl; j > 1;j--){
int summe = 1;
for(i = 2; i*i < j; i++){
if(j % i == 0)
summe = summe + i + j/i;
 
Also die erste Schleife durchläuft alle Zahlen j bis zu die von dir eingebenen.
Die zweite Schleife überprüft alle Zahlen i bis zur aktuellen Zahl j ob sie Teiler
von i sind, wenn ja werden sie auf die Summe aufsummiert.

Als optimierung muss man zum letzten Punkt erwähnen das es nicht notwendig ist die kompletten Zahlen i bis zur aktuellen Zahl j zu überprüfen, da wenn ein Teiler
bekannt ist, automatisch der zweite auch bekannt ist:
summe = summe + i + j/i;
Und somit ich nur bis zur Wurzel von j überprüfen brauch ob die Zahl i ein Teiler ist oder nicht.
Ich hoffe das ist einigermassen klar...

Gruß

RedWing
 
Hallo!

Diese Optimierung findet man auch oft bei "Pirmzahlsuch Progrämmchen".
Wenn du testen willst ob eine Zahl n durch Zahlen <=n ohne Rest Teilbar sind
reicht es nur die Zahlen von 1 bis i zu mit i^2 < n da:
Es reicht vollkommen die Schleife nur von '2' bis zur Wurzel aus 'n' zu durchlaufen, da, wenn es eine Zahl 'm' gibt, die größer als die Wurzel aus 'n' ist durch die 'n' teilbar ist, dann muss der Quotient aus 'n' und 'm' eine Zahl sein, welche kleiner als die Wurzel aus 'n' ist. Durch diese Zahl ist 'n' dann wohl auch teilbar und deswegen reicht es die Schleife von '2' bis zur Wurzel aus 'n' durchlaufen zu lassen. Um die Wurzel nicht berechnen zu müssen sollte man dann überprüfen ob das Quadrat der jeweiligen Zahl 'i' kleiner als 'n' ist, denn wenn 'i' kleiner ist als die Wurzel aus 'n', dann ist 'i*i' kleiner als 'n'.

Gruß Tom
 
Code:
for(j = zahl; j > 1;j--) /*erste schleife, sie durchläuft alle zahlen bis j*/ aber wozu größer 1 und j um einen wert veringern?
 
{
int summe = 1;
for(i = 2; i*i < j; i++) /* hier das selbe. i=2, i*i, i wird um eine zahl addiert*/
{
if(j % i == 0) /*wenn j teiler von i dann wahr*/
summe = summe + i + j/i;
 

Neue Beiträge

Zurück