Na prośbę Buły umieszczam kody pozostałych:
-Oreca:
//*****************************************//
//** Autor: Oreca **//
//** Język: C++ **//
//** Ostatnia modyfikacja: 4.08.2010 **//
//*****************************************//
#include <stdio.h>
bool JestDoskonala(int liczba)
{
int suma = 0; //suma wszystkich dzielników
for(int i = 1; i <= liczba/2; ++i)
{
if(liczba%i == 0) //Jesli liczba dzieli się bez reszty przez i to dodajemy ją do sumy
{
suma += i;
}
}
if(suma == liczba) //Sprawdzamy czy suma wszystkich dzielnikow jest taka sama jak liczba
return true;
else
return false;
}
bool JestLiczbaPierwsza(int liczba)
{
for(int i = 2; i < liczba; i++) //Zmiennej "i" przypisujemy 2 po to aby pominac dzielenie przez 1 i uruchamiamy petle
{
if(liczba%i == 0) //Jesli wynik z dzielenia przez jakakolwiek liczbę nie zwróci reszty oznacza to, ze liczba ma wiecej
{ //niz dwa dzielniki i nie jest liczba pierwsza
return false;
}
}
return true;
}
int OdwrocLiczbe(int liczba)
{
int odw = 0; //liczba odwrocona
while(liczba != 0) //Rob dopoki liczba jest inna niz 0
{
odw = (odw * 10) + (liczba % 10); //Wpierw mnozymy odw * 10 potem wyciagamy ostatnia liczbe i sumujemy wszystko czyli np
//0 * 10 + 12345 % 10 = 0 + 5 = 5
liczba /= 10; //Usuwamy ostatnia liczbe czyli np
//12345 / 10 = 1234,5 my bierzemy tylko calosc czyli 1234
//i tak dalej az do konca petli
}
return odw;
}
bool JestTakaSama(int liczba)
{
if(liczba == OdwrocLiczbe(liczba)) //Jesli liczba jest taka sama jak odwrocna liczba to funkcja zwraca true
{
return true;
}
else
{
return false;
}
}
void RozkladNaCzynnikiPierwsze(int liczba)
{
if(liczba > 1) //Sprawdzamy czy liczba jest wieksza od 1
{
printf("Rozklad liczby %i na czynniki pierwsze\n\n",liczba);
for(int i = 2; i < liczba; i++) //Zaczynamay od 2 bo przez 1 niema sensu dzielic
{
while((liczba % i) == 0) //Dzielimy nasza liczbe dopoki dzielenie nie bedzie zwracac reszty
{ //jezeli zwroci reszte to znak ze trzeba szukac innej liczby ktora sie dzieli
printf("%i|%i\n",liczba,i);
liczba /= i;
}
if(i > liczba) //Jezeli i jest wieksze od aktualnej liczby to konczymy petle
break;
}
if(liczba > 1)//Jezeli nieda sie juz podzielic przez dwa to dzielimy przez pozostala liczbe
{
printf("%i|%i\n\n",liczba,liczba);
}
}
}
int main()
{
int liczba, wybor;
while(true)//Nieskonczona petla
{
printf("1 - Sprawdz czy dana liczba jest doskonala\n"
"2 - Sprawdz czy dana liczba jest liczba pierwsza\n"
"3 - Sprawdz czy odwrotnosc liczby jest taka sama jak dana liczba\n"
"4 - Rozloz liczbe na czynniki pierwsze\n"
"5 - Wyjscie\nWybor: ");
if(!scanf("%d",&wybor))//Jezeli jakis debil wpisze litere to konczymy zabawe
{
return 0;
}
if(wybor == 5)//Jesli wybrano 5
{
return 0; //Konczymy program bo wybrano 5
}
printf("Podaj liczbe: ");
if(!scanf("%d",&liczba))//Jezeli jakis debil wpisze litere to konczymy zabawe
{
return 0;
}
switch(wybor)
{
case 1:
{
if(JestDoskonala(liczba))
{
printf("\nLiczba jest doskonala.\n\n");
}
else
{
printf("\nLiczba nie jest doskonala.\n\n");
}
break;
}
case 2:
{
if(JestLiczbaPierwsza(liczba))
{
printf("\nLiczba jest liczba pierwsza.\n\n");
}
else
{
printf("\nLiczba nie jest liczba pierwsza.\n\n");
}
break;
}
case 3:
{
if(JestTakaSama(liczba))
{
printf("\nLiczba jest taka sama jak liczba czytana od konca.\n\n");
}
else
{
printf("\nLiczba nie jest taka sama jak liczba czytana od konca.\n\n");
}
break;
}
case 4:
{
RozkladNaCzynnikiPierwsze(liczba);
break;
}
default:
{
return 0; // Konczymy program
}
}
}
return 0;
}
i
-LordSmarkula - LordSmarkula.h:
using namespace std;
//-------------------------------Liczba Doskonala------------------------------------------
bool LD(int n) //funkcja zwracająca argument prawdy lub fałszum, pobiera zmienną n
{
int m=0; //Tworzy liczbę m, która będzie sumą wszystkich dzielników liczby n
int p=(n/2)+1; //Tworzy zmienną o wartości połowy n+1, żaden dzielnik nie może być większy od połowy.
for (int o=1; o<=p; o++)//Pętla trwająca aż liczba powtórzeń (jednocześnie sprawdzane dzielniki) nie przekroczy liczby p
{ if (n%o==0) //Jeśli reszta z dzielenia n prze o wynisi zero, znaczy to, że o jest dzielnikiem n.
{m=m+o;}//dodajemy liczbę o do zmiennej m
}
if (m==n) // jeśli m (suma dzielmników) i n są sobie równe, oznacza to, że liczba n jest liczbą doskonałą
{
return true; // funkcja zwraca warunek true
}
else
{
return false;//funkcja zwraca warunek false
}
};
//--------------------------------Liczba Pierwsza----------------------------------------
bool LP(int n)
{
if (n==1)//sprawdza czy liczba n jest równa 1, jeśli tak zwraca argument false. W innym wypadku liczba 1 zostanie zwrócona jako liczba pierwsza. Można dodać dodatkowy warunek w pętli, jednak ten sposób jest oszczędniejszy
{return false;}
int m = 0; // tworzymy zmienną która będzie zliczać ilość dzielników sprawdzanej liczby.
for (int o=1; o<=(n/2); o++)//tworzymy pętlę, która będzie trwać, aż liczba o (kolejno sprawdzane dzielniki), nie przekroczy połowy liczby n (dzielnik, nie może być większy od połowy liczby), jeśli liczba dzielników jest równa 1, to liczba jest zwracana jako liczba pierwsza. Liczba dzielników liczby pierwszej jest równa 2, jednak w ten sposób oszczędzamy zasoby komputera, sprawdzając tylko dzielniki do połowy liczby, przez co liczby pierwsze będą miały tylko jeden dzielnik, powstaje w ten sposób problem z 1, który wykluczamy na początku programu.
{ if (n%o==0)//sprawdza czy zmienna o jest dzielnikiem zmiennej n.
{
m=m+1;//jeśli jest dodajemy 1 do m.
if(m==2) //jeśli m jest równe dwa zwracamy argument false, ponieważ liczba ma więcej dzielników niż powinna mieć liczba pierwsza
{return false;}
}
}
return true; //Jeśli pętla zakończyła swoje działanie bez zwrócenia argumentu false, oznacza to, że liczba n jest liczbą pierwsza, zwracamy argument true.
};
//-----------------------------Liczba czytana od tyłu--------------------------------------
bool OT (string n) // ta funkcja w przeciwieństwie do innych pobiera string.
{
string m; //tworzenie nowego, pustego stringa.
int d;
d=n.length(); //int o długości stringa, potrzebny do pętli
char a; //pojedynczy char, pobierający znak z n, następnie wstawiany na koniec m.
for (int p=1; p<d+1; p++) // pętla trwająca aż liczba powtórzeń nie przekroczy długości n
{
a=n.at(d-p); //char a pobiera znak o położeniu d(długość stringa - ostatni znak) - liczba powtórzeniń. w ten sposób pobiera kolejno znaki od końca
m+=a; // a nestępnie te znaki wstawiamy do m, dzięki czemu m, będzie odwrotnością n
}
if (n==m) // jeśli string n i m są sobie równe
{return true;} //zwracamy argument true
else//...
{return false;}
};
//----------------------------Rozkład na czynniki pierwsze---------------------------------
void CP (int n)//ta funkcja nic nie będzie zwracać dlatego jest void
{
int v=0; // v będzie kolejno sprawdzanymi liczbami do czynnika pierwszego
int x =0;//zmienna służąca do pętli do while, zmienna ta nie będzie w ogóle używana ponieważ z funkcji wychodzimy poprzez break
int y=0;//zmienna, któa będzie sprawdzała czy n się zmieniała
do
{
cout << n << '|'; //wypisuje aktualne n i pionową kreskę
if (LP(n))//jeśli aktualne n jest liczbą pierwszą wypisze ją jako ostatni czynnik pierwszy i zakończy pętlę
{cout << n << endl << '1' << '|' << endl << endl; break;}
do
{
y=n; // y przyjmuje warstość n
v++; // v wzrasta o jeden
if (LP(v))// jeśli v jest liczbą pierwszą...
{
if (n%v==0)// to sprawdza, czy n jest podzielne przez v.
{cout << v << endl; // jeśli tak to wypisuje v jako kolejny czynnik pierwszy i schodzi do następnego wiersza
n=n/v;}//oraz dzieli n przez v
}
}
while(y==n);//pętla trwa dopóki y = n, gdy znajdziemy kolejny czynnik pierwszy n jest dzielone przez v, wtedy to równanie jest niepoprawne i wychodzi z tej pętli
v--;//ponieważ kolejne czynnik pierwsze mogą być tylko większe, bądź równe poprzednim czynnikom pierwszym zamaiast zerować v i sprawdzać kolejno liczby od 1, to odejmujemu 1 od v (na początku pętli jest v++, więc musimy tutaj odjąć 1)
}
while(x==0); // tutaj warunek pętli jest spełniony cały czas, z pętli wychodzimy poprzez break;
};
oraz main.cpp:
#include <cstdlib>
#include <iostream>
#include "LordSmarkula.h"
using namespace std;
int main()
{ int p;
int r=0;
do
{
cout << "1-Sprawdzenie, czy liczba jest liczba doskonala \n2-Sprawdzenie czy liczba jest liczba pierwsza \n3-Sprawdzenie, czy liczba czytana odwrotnie jest ta sama liczba \n4-Rozklad liczby na czynniki pierwsze\n5-Zakonczenie programu\n";
cin >> p;
if (p>5)
{
system("CLS"); cout<< "Podano zle zadanie. \n";
}
else
{
if (p==1)
{ system("CLS");
cout << "Podaj liczbe do sprawdzenia.\n";
int n;
cin >> n;
if (LD (n)) cout<<"Liczba " << n << " jest liczba doskonala.\n\n";
else cout<<"Liczba " << n << " nie jest liczba doskonala.\n\n";
}
else if (p==2)
{
system("CLS");
cout << "Podaj liczbe do sprawdzenia.\n";
int n;
cin >> n;
if (LP (n)) cout<<"Liczba " << n << " jest liczba pierwsza.\n\n";
else cout<<"Liczba " << n << " nie jest liczba pierwsza.\n\n";
}
else if (p==3)
{
system("CLS");
cout << "Podaj liczbe do sprawdzenia.\n";
string m;
cin >> m;
if (OT(m)) cout<<"Liczba " << m << " czytana od tylu jest ta sama liczba.\n\n";
else cout<<"Liczba " << m << " czytana od tylu nie jest ta sama liczba.\n\n";
}
else if (p==4)
{
system("CLS");
cout << "Podaj liczbe do sprawdzenia. \n";
int n;
cin >> n;
CP (n);
}
else if (p==5) break;
}
}while (r==0);
system("PAUSE");
return EXIT_SUCCESS;
}
Moja ocena z każdego z programów.
LordSmarkula:
Uwagi:
* Zamiast tego:
if (m==n) // jeśli m (suma dzielmników) i n są sobie równe, oznacza to, że liczba n jest liczbą doskonałą
{
return true; // funkcja zwraca warunek true
}
else
{
return false;//funkcja zwraca warunek false
}
można po prostu dać return (m==n); ;)
* 0 i ujemne są liczbami pierwszymi wg twojego programu, ale to szczegół ;)
* pętle for można zacząć od 2, wtedy m by się nie zwiększało, bo jeśli się znajdzie dzielnik liczby n między [2,n/2], to już nie jest pierwsza
* to samo co w liczbach pierwszych:
if (n==m) // jeśli string n i m są sobie równe
{return true;} //zwracamy argument true
else//...
{return false;}
* niepotrzebne dwie pętle do-while, wystarczyłaby jedna
* niepotrzebne sprawdzanie, czy v jest pierwsza
* zawiesza się przy sprawdzaniu dzielników 1
* pasowałoby robić jednowierszowe odstępy między inicjowaniem zmiennych a instrukcjami, czyli np.
int zmienna;
if (zmienna)
{
}
IMO zwiększa to czytelność
* dość dobrze skomentowany kod
[/list]
Oreca
Uwagi:
* Zamiast tego
if(suma == liczba) //Sprawdzamy czy suma wszystkich dzielnikow jest taka sama jak liczba
return true;
else
return false;
można po prostu dać return (suma == liczba); ;)
* 0 i ujemne są liczbami pierwszymi wg twojego programu, ale to szczegół ;)
* ale 1 też wg twojego programu jest...
* pętle for można skrócić do liczba/2 +1
w funkcji JestTakaSama można skrócić podobnie jak w funkcji JestDoskonala
* niepotrzebne użycie dwóch pętli for, a w niej while i break; lepiej by było użyć petli while, a w niej instrukcji if
* dość dobrze skomentowany kod, ale pasowałoby w niektórych miejscach użyć wcięć ;)
* mała uwaga od twórców języka C (Kernighan, Ritchie) dotycząca tego:
case 4:
{
RozkladNaCzynnikiPierwsze(liczba);
break;
}
default:
{
return 0; // Konczymy program
}
"Do dobrego stylu programowania należy wstawianie break po ostatniej instrukcji ostatniego przypadku, mimo że nie jest to konieczne. Pewnego dnia, gdy dopiszesz na końcu jakiś inny przypadek, ta odrobina zapobiegliwości może Cię uratować."
[/list]