Prime generator - co z tą pętlą (prawdopodobnie)?

0

Wiem, że gdzieś już był ten temat, ale nie został rozwiązany. Mi chodzi bardziej o wskazanie błędu w moim kodzie. Może któryś z bardziej doświadczonych użytkowników znajdzie chwilę. Funkcja, docelowo, ma generować wszystkie liczby pierwsze z zadanego, przez użytkownika, przedziału. //spr. oznacza sprawdzenie czy do zmiennej zapisałem dobra wartość.

#include <iostream>
#include <stdio.h>
#include <cstdlib>

using namespace std;

int ifFirst(int n, int m){
    int counter=0;// licznik dzielników
    int w=0;//zmienna służąca do której zapisywane są kolejne Liczby pierwsze z zadanego przedziału, (n,m)
    int tmp=0;// zmienna pomocnicza, potrzebna, moim zdaniem w forze
    tmp=n;
    cout<<"tmp = "<< tmp <<endl;//spr.
    for(int i=n; i<=m; i++){
        tmp=tmp+i-n;
        for(int i = 2; i<=(tmp/2); i++){
            w=tmp;
            cout<<"w = " << w<< endl; //spr.
            if(w%i==0){
                counter++;
            }
            if(counter == 0){
                cout<<w<<endl;}
        }
    }

    }

int main(){
    cout<< "podaj liczbe testow: "<<endl;
    int t;
    int k, p;
    cin>>t;
    for(int i = 0; i<t; i++){
        scanf("%d %d",&k,&p);
        cout << k << " " << p<<endl;//spr.
        ifFirst(k, p);
        k=0;
        p=0;
    }

return 0;
}

Nie działa to tak jak powinno i nie bardzo wiem dlaczego. Problem ewidentnie siedzi w ciele funkcji ifFirst. Drugi for wariuje. Link do oryginalnego problemu na SPOJu: http://www.spoj.com/problems/PRIME1/

1

i tak Ci to nie przejdzie na spoju bo bedzie za wolne

musisz skorzystac z sita Eratostenesa

szukaj, tematow bylo wiecej niz mam wlosow na glowie

0

Ok, ok, ale już abstrachując od SPOJa, czy miałbyś sekundę by spojrzeć co jest nie tak w tej funkcji?

0
if(counter == 0){

To powinno być po for. Przecież chcesz sprawdzić tylko raz na samym końcu czy liczba ma 0 dzielników.

Za cholerę nie rozumiem tego cyrku z tmp.

w=tmp;

tmp się nie zmienia, czyli za każdym razem w ma tę samą wartość.

No i tak jak @fasadin napisał, możesz poprawić swój program, żeby był poprawny, ale na pewno nie przejdzie na spoju bo będzie za wolny.

0

Ok, z tym tmp trochę poleciałem. Trochę to uprościłem, dalej jest nie bardzo:

 #include <iostream>
 #include <stdio.h>
 #include <cstdlib>

using namespace std;

int ifFirst(int n, int m){
    int counter=0;//licznik dzielników
    int w=0;// zmienna, do której zapisywana jest kolejna sprawdza liczba
    w=n;//inicjalizacja w na początku przedziału
    for(int i=n; i<=m; i++){
        w=w+i-n;// na początku i = n, z kazdym obiegiem pętli większe, więc w powinno zwiększać się o 1 wraz z każdym obiegiem tego fora
        for(int j = 2; j<=(w/2); j++){
            if(w%j==0){counter++;}//j to dzielniki, jeśli dzielą w to zwiększam licznik dzielników
        }
        if(counter == 0){cout<<w<<endl;}//jesli nie ma dzielników to drukuję w
    }

    }

int main(){
    cout<< "podaj liczbe testow: "<<endl;
    int t;//liczba testów
    int k, p;
    cin>>t;
    for(int i = 0; i<t; i++){
        scanf("%d %d",&k,&p);
        cout << k << " " << p<<endl;//spr.
        ifFirst(k, p);
        k=0;
        p=0;
    }

return 0;
}

 
0
int w=0;
w=n;

widzisz bezsens tych 2 linijek stojących razem? W dodatku żadna inicjalizacja nie jest potrzebna.

w=w+i-n;

dlaczego nie w = i;?

Nie zerujesz counter po wejściu do pętli.

0
smolin1 napisał(a):

Ok, z tym tmp trochę poleciałem. Trochę to uprościłem, dalej jest nie bardzo:


 #include <stdio.h>

powinno być

#include <cstdio>

[...]
        w=w+i-n;// na początku i = n, z kazdym obiegiem pętli większe, więc w powinno zwiększać się o 1 wraz z każdym obiegiem tego fora

w nie zwiększa się o 1!

        for(int j = 2; j<=(w/2); j++){
            if(w%j==0){counter++;}//j to dzielniki, jeśli dzielą w to zwiększam licznik dzielników
        }

Napisano już , że to nieoptymalne, ale jeszcze bardziej nieoptymalne z tego powodu, że zlicza niepotrzebnie
po wtóre counter jest niezerowane przed pętlą, po 3 - jak wskoczy na 1 to już wiadomo, że nie jest liczbą pierwszą i warto przerwać pętlę

0

Wielkie dzięki za pomoc, wasze rady okazały się trafne. Po wyzerowaniu licznika i dobrym zainicjalizowaniu "w". Wszystko działa (chyba) tak jak powinno. Co do tego <cstdio> To on nie ma scanfa(przynajmniej mój code::blocks sie buntował), a scanf ładnie zbiera te dwie liczby po spacji. Finalna wersja:

#include <iostream>
#include <stdio.h>

using namespace std;

int ifFirst(int n, int m) {
  if (1 > n || m > 1000000000 || m - n > 100000) {
    return 0;
  }
  int counter = 0;
  int w = 0;
  for (int i = n; i <= m; i++) {
    w = i;
    for (int j = 2; j <= (w / 2); j++) {
      if (w % j == 0) {
        counter++;
        break;
      }
    }
    if (counter == 0) {
      cout << w << endl;
    }
    counter = 0;
  }
}

int main() {
  cout << "podaj liczbe testow: " << endl;
  int t;
  int k, p;
  cin >> t;
  if (t > 10) {
    return 0;
  }
  for (int i = 0; i < t; i++) {
    scanf("%d %d", &k, &p);
    ifFirst(k, p);
    k = 0;
    p = 0;
  }

  return 0;
} 

Ze SPOJem też racja. Idę szukać tego sita. Dzięki wielkie za pomoc! :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1