Liczba pierwsza <1;n> C++


(Arko Polo) #1

Witam, to moja pierwsza wiadomość na tym forum. Nie chcąc nikomu podpaść od razu zastosuję się do instrukcji "Zanim cokolwiek..." Mam Windows 7 HP 64 bit, korzystam z Dev c++ 5.2.0.3. Mam za zadanie napisać na kółko program w C ++, który dla podanego n wypisze liczby pierwsze w przedziale od 1 do n. Z racji, że dopiero zaczynam moją przygodę z programowaniem nie bardzo widzę, gdzie zrobiłem błąd.

#include 

#include 

using namespace std;

int main ()

{

 long n;

 do

 {

 cout << "Podaj n";

 cin >> n;

 bool p=true;

 for (int i=1; i
 if (n%i==0)

 p=false;

 if (p)

 cout << i;

 getch();

}

while (i==n);

}

Program nie chce się skompilować. Oto log kompilacji:

Kompilator: MinGW GCC 4.6.2 32-bit

Wykonywanie g++.exe...

g++.exe "D:\cosie\szkoła\2b\kólko\liczba pierwsza w przedziale.cpp" -o "D:\cosie\szkoła\2b\kólko\liczba pierwsza w przedziale.exe" -I"C:\Program Files (x86)\Dev-Cpp\MinGW32\include" -L"C:\Program Files (x86)\Dev-Cpp\MinGW32\lib" -static-libstdc++ -static-libgcc 

D:\cosie\szkoła\2b\kólko\liczba pierwsza w przedziale.cpp: In function 'int main()':

D:\cosie\szkoła\2b\kólko\liczba pierwsza w przedziale.cpp:16:10: error: name lookup of 'i' changed for ISO 'for' scoping [-fpermissive]


D:\cosie\szkoła\2b\kólko\liczba pierwsza w przedziale.cpp:16:10: note: (if you use '-fpermissive' G++ will accept your code)

D:\cosie\szkoła\2b\kólko\liczba pierwsza w przedziale.cpp:19:8: error: 'i' was not declared in this scope


Wykonanie zakończone

Chciałbym dowiedzieć się, w którym konkretnie miejscu/miejscach popełniłem błąd lub błędy.

Pozdrawiam


(Kopczynski1991) #2

Na pierwszy rzut oka widać, że pętla nie ma klamerek { } więc będzie ona wykonywała tylko jedno linijkę instrukcji:

if (n%i==0)

, jeśli deklarujesz w pętli for zmienną “i” to ta zmienna jest tylko widzialna w tej pętli, program dalej jej nie widzi, więc przy napotkaniu tej linijki:

cout << i;

kompilator zapewne wywali błąd…


(system) #3

Żaden pr0 z programowania ze mnie nie jest, ale:

  1. Jeżeli masz więcej niż jedną instrukcję w pętli for to miś być ona w odzianym bloku kodu (czyli {})

  2. Dodaj jeszcze jedną } przed while

  3. Formatuj kod


(Drobok) #4

Pomijając w/w porady (pod którymi się podpisuje).

Getch w pętli będzie wymuszał klikanie enter po każdym przejściu

conio.h jest nieprzenośne

pomijając fakt braku zmiennej i poza pętlą (odwołujesz się do niej również w warunku while), jeśli dałbyś ją poza for wychodziłbyś z while zaraz po for :slight_smile:

Co do samego problemu, jeśli użyłbyś tablicy dynamicznej i zapisywał wyniki, wystarczyło by dzielić tą liczbę przez elementy tej tablicy. A i powinno iść co 2 (co druga liczba jest podzielna przez 2)


(Drobok) #5

W twoim przykładzie jest dużo zbędnego kodu, oraz jest on mało praktyczny przy większym n :slight_smile:


(Arko Polo) #6

Doszedłem do wniosku, że mój kod nie ma potencjału. A jeśli ma, to ja go nie dostrzegam. Poprawiłem trochę go podług zaleceń, jednak nadal nici. Co prawda kompiluje się ładnie, ale gdy uruchomię program, to jak gdyby liczył coś, ale nic nie wyskakuje. Doczytać sporo muszę. Jeśli wystąpią problemy, to będę wiedział, gdzie się zgłosić. Dziękuję, miłego wieczoru.


(Drobok) #7

Akurat uważam że dyskusja tutaj jest niezbędna. Twój algorytm jest bardzo słaby, a klasy użyłeś tylko po to by jej użyć.


(Rolek0) #8

@up Niepotrzebne nadużywanie mechanizmów językowych raczej nie ułatwia zrozumienia, szczególnie początkującemu :stuck_out_tongue:

@op Polecam douczyć się trochę C++, np. stąd http://xion.org.pl/productions/texts/coding/megatutorial/ lub http://www.intercon.pl/~sektor/cbx/ oraz używać jakiegoś innego IDE np. Code::Blocks, Dev-C++ jest przestarzałe.

A przykładowy kodzik :wink:

// Sito Eratostenesa

// http://pl.wikipedia.org/wiki/Sito_Eratostenesa


#include 

#include 

using namespace std;


int main()

{

	size_t n;

	cin >> n;

	vector sito(n + 1); // vector lepszy niż goła tablica :P

		// http://www.cplusplus.com/reference/stl/vector/


	for(size_t i = 2; i < sito.size(); ++i)

		for(size_t j = i + i; j < sito.size(); j += i)

			sito[j] = true; // wykreślanie


	for(size_t i = 2; i < sito.size(); ++i)

		if(!sito[i])	

			cout << i << endl; // wypisywanie


	return 0;

}

([alex]) #9

Jako ciekawostka, sito Eratostenesa na mapie bitowej z wstępnym pominięciem liczb podzielnych przez 2 i 3.

void prime1(unsigned n)

  {

   static const unsigned char hs[]={8,0,8,8,8,1,8,2,8,8,8,3,8,4,8,8,8,5,8,6,8,8,8,7};

   unsigned mx=(n+23)/24;

   unsigned char *tb=new unsigned char[mx];

   memset(tb,0,mx);

   //tb[0]=1; // 1 nie jest liczbą pierwszą, ale i tak zaczynamy od 5-ki

   if(3
   else if(2
   for(unsigned x=5,d=2,p=1,i=0;x
     {

      if(!(tb[i]&(1<

        {

         cout<
         for(unsigned vx=5*x,vd=2;vx
           {

            unsigned i=vx/24,m=vx-i*24,q=hs[m];

            tb[i]|=1<<(q);

           }

        }

     }

   delete[] tb;

  }

Umożliwia to wpakowanie 24 liczb w jeden bajt.

Można na tej samej zasadzie pominąć wstępnie liczby podzielne przez 2,3,5 wtedy można wpakować 30 liczb w jeden bajt.

Oprócz oszczędzania pamięci zwiększamy też szybkość obliczeń, ponieważ musimy wykreślić polowe tablicy dla liczb podzielnych przez 2 oraz 1/3 tablicy dla liczb podzielnych przez 3.

Eliminując również 5-ki zyskujemy kolejne 20% pamięci oraz szybkości.

Z 7-ką już nie jest to tak różowo :smiley: