delphi liczby pierwsze

0

Witam, na początek chcę powiedzieć, że czytałam wszystkie wątki dotyczące liczb pierwszych na tym forum, więc proszę mnie nie kasować i odsyłać do wyszukiwarki. Jednym słowem: proszę o litość.

Mam do napisania kilka zadań na zaliczenie. Jestem na informatyce na studiach, ale nigdy wcześniej nie miałam do czynienia z programowaniem. Tak to jest jak głupia baba się uprze na polibudę tuż po liceum humanistycznym ;/ Mogę też dla usprawiedliwienia mej niewiedzy dodać, że na razie mieliśmy trzy godziny z jakimś zastępcą, który nic nam nie tłumaczył itd... Dlatego proszę, podpowiedzcie mi jak ruszyć te programy. Nie chcę gotowców - ja naprawdę chcę to zrozumieć. I na serio czytam książki, szukam w necie - ale nie ogarniam.

No to do rzeczy. Polecenie brzmi: Napisz program wypisujący wszystkie liczby pierwsze z przedziału [a,b].

Moim pierwszym problemem jest jak zrobić ten przedział. Kombinowałam coś żeby były polecenia typu: podaj najmniejszą liczbę, podaj największą liczbę, ale nie wiem co dalej. Myślałam o jakiejś tablicy, ale nie wiem jak to ruszyć.

0

Hmmm, na podstawie tego co znalazłam w necie coś takiego na razie mi wyszło... Mógłby ktoś się wypowiedzieć? Działać działa, choć strasznie dużo enterów trzeba klikać...

program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils;

   var i,j,L,a,b: Integer;
begin
  write('podaj najmniejsza liczbe ');
  readln(a);
  write('podaj najwieksza liczbe ');
  readln(b);

  for a:=a to b do begin
     L:=0;
     for j:=1 to a do
     if (a mod j)=0 then L:=L+1;
     if L= 2 then writeln(a);
     readln;

  end;

end.
0

Do tego użyj for'a.

Program LiczbyPierwsze;                              { Nazwa programu                      }
{$APPTYPE CONSOLE}                                   { Ustalenie, że to program konsolowy  }
Var IleLiczb, I: Integer;                            { Zmienne                             }

Function CzyLiczbaPierwsza(P: Integer): Boolean;     { Funkcja                             }
Var I: Integer;                                      { Zmienna                             }
Begin                                                { Początek funkcji                    }
 Result := True;                                     { Ustawienie wyniku na 'tak'          }
 I      := 2;                                        { Ustawienie zmiennej I na 2          }
 While (I < P) Do                                    { Dopóki I < P                        }
  if (P Mod I = 0) Then                              { Jeżeli P Mod I = 0                  }
  Begin
   Result := False;                                  { Liczba nie jest liczbą pierwszą     }
   Break;                                            { Przerwij działanie pętli While      }
  End
  Else                                               { Jeżeli P Mod I <> 0                 }
  Inc(I);                                            { Zwiększ I o 1                       }
End;                                                 { Koniec funkcji                      }

Begin                                                { Główny blok programu                }
 WriteLn('*** Obliczanie liczb pierwszych ***');     { Wstęp                               }
 WriteLn;                                            { (enter)                             }
 Write('Ile liczb znalezc: ');                       { Ile liczb znaleźć ?                 }
 ReadLn(IleLiczb);                                   { Zczytaj wartość od użytkownika      }
 For I := 2 To IleLiczb Do                           { Pętla, od I do 'IleLiczb'           }
  if (CzyLiczbaPierwsza(I)) Then                     { Jeżeli 'CzyLiczbaPierwsza(I)' = TAK }
   WriteLn(I);                                       { Wyświetl tę liczbę                  }
 ReadLn;                                             { Czekaj na enter                     }
End.
0

Ubiegłaś mnie, jak pisałem posta...

program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils;

   var i,j,L,a,b, mi: Integer;
begin
  write('podaj najmniejsza liczbe ');
  readln(mi);
  write('podaj najwieksza liczbe ');
  readln(b);

  for a:=mi to b do begin
     L:=0;
     for j:=1 to a do
     if (a mod j)=0 then L:=L+1;
     if L= 2 then writeln(a);


  end;
     readln; //ReadLn tutaj i nie trzeba naciskać co liczbę
end.

Ale dobrze wyświetla ;)

for a:=a to b do begin

Tak się nie robi ! (na przyszłość).

0

A możesz powiedzieć mi co miałeś na myśli pisząc 'tak się nie robi'? Mówię wprost - nie napisałam tego zupełnie sama, przerabiałam tylko te programy, które znalazłam w sieci, więc choć widzę, że działa i wiem na jakiej zasadzie (sprawdza czy każda liczba jest podzielna tylko przez samą siebie i jeden) to dopiero próbuję dokładnie to rozgryźć w razie nauczyciel by nas spytał dlaczego tak a nie inaczej.
I wielkie dzięki za to przestawienie 'readln' bo się głowiłam jak sprawić, by nie trzeba było tyle klikać :*

0

To tak trochę nielogicznie wygląda (wg.mnie).

For A:=A To B Do

Ale to zależy od programisty (programistki) jak użyje ;)
Może ktoś inny się wypowie ?

0

Aha, łapię ;) Twoją wersję przeanalizowałam sobie jeszcze i jest dla mnie bardziej zrozumiała, ale ma tę wadę, że najmniejsza liczba jest stałą, a konkretniej dwójką. Póki co zostanę więc przy 'moim' pomyślę. Mógłbyś jeszcze (lub ktokolwiek inny) trochę mi 'objaśnić' mój kod?

Tzn. tak liczę w pętli od 'j' do którego jest przypisana jedynka do 'mi'. Sprawdzam, czy reszta z dzielenia 'mi' przez 'j' jest równa 0. Jeśli tak to do L dodaje 1 i w ten sposób powstaje kolejne nowe L, większe o jeden. I potem jeśli L jest równe dwa wypisuję a. I teraz proszę o wyjaśnienie czym jest to całe L??? Jeśli pytam jak klasyczny nieuk to bardzo przepraszam, ale staram się to pojąć... :)

0

Dobra, dobra, przepraszam, już wiem - L to ilość takich wyników, gdy reszta wynosi 0. I jeśli są tylko dwa takie wyniki to mamy liczbę pierwszą :D Musiałam to sobie tylko rozpisać ;))) Matko, a cały dzień nad tym programem siedziałam (nie wspominając o wielu podejściach w dni poprzednie)... :))))

0

Hallo wampirzyc(a)!

W zasadzie nie wiem, czy powinienem to robic, ale jest pewna strona pewnego liceum w Tarnowie z wieloma rozwazaniami pewnych szkolnych problemow. Wpadlem na nia przypadkiem i bardzo mi sie spodobala. Zagladam tam od czasu do czasu bo czytanie zamieszczonego tam kodu to bardzo dobra gimnastyka!

Podaje link do Twojego problemu: http://edu.i-lo.tarnow.pl/inf/alg/001_search/0009.php

Pozdrawiam
Markus
:-)

0

siemka,
po przeczytaniu treści zadania wydało mi się, że komukolwiek, kto zadawał to zadanko, chodziło o użycie algorytmu Sita Eratostenesa.
Wasze rozwiązania są dobre - ale widzę możliwość kilku usprawnień: jeśli chcemy sprawdzić pierwszość liczby n, wystarczy sprawdzić, czy dzieli się bez reszty (mod) przez liczby z zakresu 2..ceil(sqrt(n)) (funkcja ceil zaokrągla do góry- aby jej użyć należy włączyć bibliotekę math przed zasadniczą częścią programu:

 uses math;
var 
//zmienne
begin
//program
end.

sqrt - wiadomo, pierwiastek.)

ja to zadanie zrobiłbym tak:

  • na pewno jest jakieś ograniczenie przedziałów. tak więc za pomocą sita eratostenesa wyznaczam wszystkie liczby pierwsze od 2 do górnego ograniczenia. konstruuję tablicę booleanów, od 2 do górnego ograniczenia, która dla zadanej liczby zwróci TRUE jeśli liczba jest pierwsza, i false, jeśli złożona. na początku działania algorytmu założymy, że wszystkie liczby w tablicy mają wartość TRUE, i będziemy je eliminować

Sito Eratostenesa działa mniej więcej tak:

  • zaczynasz od liczby 2. wiesz, że jest to liczba pierwsza. każda wielokrotność dwójki (4,6,8,10...) na pewno nie jest liczbą pierwszą, tak więc dla każdej wielokrotności dwójki, w tablicy booleanów ustawiasz FALSE
  • potem bierzesz kolejną liczbę, której nie wykreśliłaś. jest na pewno liczbą pierwszą - gdyby była złożona, zostałaby wykreślona podczas wcześniejszego działania programu. po dwójce będzie to liczba 3 - zostawiasz jej wartość true, i wykreślasz z tablicy jej wielokrotności.
  • bierzesz kolejną liczbę, która nie została wykreślona. liczba 4 już została wykluczona (przy wykreślaniu wielokrotności dwójek), więc bierzesz 5, i wykreślasz wielokrotności.
  • i tak dalej

potem, żeby Twoje zadanie dawało dobre wyniki, zrobisz tak:

program l_pierwsze;

var
i, a, b, wyn: longint;
sitko: array[1..JakasLiczba] of boolean; 

begin
writeln('Podaj dolna granice przedzialu: '); read(a);
writeln('Podaj gorna granice przedzialu: '); read(b);
wyn:=0;
//TUTAJ FRAGMENT KTORY ROBI SITO ERATOSTENESA z tablicy od 1.. do b
for i:=a to b do if sitko_zrobione[i]=TRUE then inc(wyn);
writeln('W zadanym przedziale jest ',wyn,' liczb pierwszych');
readln;
end.

komentarz:

  1. inc(zmienna_calkowita) jest równoważne zwiększeniu zmiennej o 1, czyli tak samo jak wyn:=wyn+1;
  2. tak na prawdę, nie musimy dawać: if "sitko_zrobione[i]=TRUE". wystarczy, że damy "if sitko_zrobione[i]". do instrukcji warunkowej IF trzeba przekazać wartość logiczną - a taką wartość mamy w tablicy dla i-tej liczby - albo TRUE, albo false. nieznacznie szybciej byłoby zastosowanie drugiego "if sitko_zrobione[i]", ponieważ przekazujemy instrukcji od razu wartość logiczną. natomiast w przypadku "if sitko_zrobione[i]=TRUE", najpierw podana jest wartość logiczna (np, jeśli i=7, wartość będzie true), a potem jakaś inna wartość, z którą ją porównujemy, tzn koniec końców, kompilator jeszcze oblicza wartość wyrażenia TRUE=TRUE lub FALSE=TRUE, czego nie ma przy zastosowaniu "if sitko_zrobione[i]" - ale to taki mały szczegół ;)

zadanie dla ciebie: napisz fragment programu, która zrobi "sitko" logiczne z tablicy [1..b] of boolean.
wskazówki: dla jedynki od razu zainicjuj FALSE, dla dwójki TRUE. ( sitko[1]:=false; sitko[2]:=true; )
i potem walnij pętlę, for i:=2 to b. jeśli natkniesz się na wartość prawdziwą, np. dla liczby 5, to znaczy że ta liczba jest pierwsza - i dla każdej jej wielokrotności w sitku ustaw wartość FALSE (odpowiedzialna za to inna pętla). możesz zastosować jakąś zmienną "mnoznik" żeby wiedzieć jakie wielokrotności wykreślać, i potem zrobić:

//fragment programu
mnoznik:=5;
for i:=2 to (b div mnoznik) do sitko[i]:=FALSE;
//koniec fragmentu

praktycznie wszystko masz podane - wystarczy trochę pogłówkować i złożyć to do kupy ;) Jeśli coś nie jest jasne - pisz

0

A ja kiedyś bawiąc sie liczbami pierwszymi doszedłem do wniosku ze nie ma sensu badać czy liczba n dzieli się przez którąkolwiek z zakresu (2; sqrt(n)). Wystarczy zamiast tego badać, czy liczba n dzieli się przez którąkolwiek liczbę PIERWSZĄ z zakresu (2, sqrt(n)). Wtedy można zrobić np sympatyczną listę, z której będą brane liczby pierwsze, które będą służyły do badania czy następna liczba jest pierwsza. Jeśli jest - trafia ona na tą listę. Takie jakby sprzężenie zwrotne. Wyniki działania prędzej czy później będą jego danymi.

0

Jeżeli jest niewielka ilość liczb do sprawdzenia, sprawdzanie do pierwiastka jest dobre (jeśli nie ma podzielnika w zakresie do pierwiastka z liczby, to nie będzie w zakresie powyżej pierwiastka, bo liczba jeśli ma szukane podzielniki to jest iloczynem dwóch liczb albo równych pierwiastkowi z niej albo jedna mniejsza od pierwiastka a druga większa).

Przy dużych zakresach do sprawdzenia, rozpoczynających się od zera, sito Eratostenesa jest dużo szybsze.

0

A żę tak spytam z ciekawości.
po co to

a := 1;
for a := mi to b do

?

Zamiast mi mogła wstawić 1.

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