Avatar billede gnukki Nybegynder
18. december 2007 - 19:33 Der er 34 kommentarer og
2 løsninger

Do while løkke inde i en for løkke til løsning af primtal

Godaften,

Jeg har følgende kode, der skal bruges til at finde primtal, hvor jeg undersøger om et tal kan opløses af andre tal. Jeg lavede det først med to for-løkker, dette virkede fint men der blev foretaget mange unødvendige beregninger. Jeg tænkte at jeg kunne bruge en do while løkke, så programmet hoppede til næste tal hvis det udregnede at der var et tal, der gik op i det. Jeg har følgende kode, men den virker ikke. Er der nogen der kan se hvad jeg gør forkert? :)



#include <iostream>

using namespace std;


int main(){
   
    int tabel[10] = {1,1,1,1,1,1,1,1,1,1};
    int i,j;
    tabel[0] = 0;
    tabel[1] = 0;
    for(i=2;i<11;i++){
        do{
            for(j=2;j<i;j++){
                if(i%j==0){
                    tabel[i] = 0;
                }
            } 
        }while(tabel[i]==1);                   
    }
    cout << endl;
    for(i=0;i<11;i++){
        if(tabel[i]==1)cout << i << endl;
    } 
}
Avatar billede arne_v Ekspert
18. december 2007 - 19:40 #1
et lille hint: du kan hoppe ud af en for loekke i utide ved at bruge break statement !
Avatar billede nielle Nybegynder
18. december 2007 - 19:41 #2
Din do-while køre uendeligt når det er et primtal.
Avatar billede arne_v Ekspert
18. december 2007 - 19:45 #3
andet lille hint: for at checke om n er et primtal behovber du kun dividere med tal op til kvadratrod(n)
Avatar billede gnukki Nybegynder
18. december 2007 - 19:47 #4
Mange tak Arne, det gjorde lige programmet mindst 10 gange så hurtigt. Vil du have pointene? :)
Avatar billede nielle Nybegynder
18. december 2007 - 19:47 #5
endnu et par hint:

Du behøver slet ikke at tjekke for lige tal over 2.

og en raninement til arnes hint:

for at checke om n er et primtal behovber du kun dividere med *primtal*tal op til kvadratrod(n)
Avatar billede nielle Nybegynder
18. december 2007 - 19:48 #6
raninement -> rafinement
Avatar billede gnukki Nybegynder
18. december 2007 - 19:55 #7
Grunden til jeg gør det på denne måde er at det skal udføres efter den matematiske model, Sieve of Eratosthenes. Men koden kunne måske stadig optimeres?
Avatar billede arne_v Ekspert
18. december 2007 - 19:58 #8
hvis tabel[j] ikke er sat er der ingen grund til at checke %j

og det kan optimere lidt da % er en forholdsvis dyr operation
Avatar billede nielle Nybegynder
18. december 2007 - 19:58 #9
Den algoritme du har der er nu altså ikke Sieve of Eratosthenes.

Ja, din kode kan optimeres med de hints du har fået. :^9
Avatar billede arne_v Ekspert
18. december 2007 - 19:59 #10
code snippet:

  for(i=2;i<=p;i++) sieve[i]=TRUE;
  for(i=2;i<=sqrtp;i++) if(sieve[i]) for(j=2*i;j<=p;j=j+i) sieve[j] = FALSE;
Avatar billede nielle Nybegynder
18. december 2007 - 19:59 #11
18/12-2007 19:58:11> der er jo sådan set netop det jeg siger sidst i 18/12-2007 19:47:53 :^)
Avatar billede arne_v Ekspert
18. december 2007 - 20:01 #12
jep
Avatar billede gnukki Nybegynder
18. december 2007 - 20:02 #13
er jeg helt fuldstændigt forkert på den for at lave Sieve of Eratosthenes?
Avatar billede nielle Nybegynder
18. december 2007 - 20:05 #14
Ja, med den angivne algoritme er du. SoE bruger sådan set slet ikke % men ganger i stedet og fjerner multipla.

Som 18/12-2007 19:59:41
Avatar billede gnukki Nybegynder
18. december 2007 - 20:06 #15
Nu er jeg ikke helt med, har du et forslag til hvordan dette gøres?
Avatar billede nielle Nybegynder
18. december 2007 - 20:13 #16
Arne har sådan set allerede givet koden.

Man starter med et aray op til den størelse man ønsker at finde primtallene inden for.

Trin 1) Så starter man med 2. Fra denne sætter man et hak henover alle multipla af 2: 4, 6, 8, 10, ... indtil man løber "ovenud" af arrayet.

Trin 2) Derefter går man vidre til det næste tal hvor der ikke allerede er et hak. Det er 3. Fra denne sætter man et hak henover alle multipla af 3: 6, 9, 12, 15, ... indtil man løber "ovenud" af arrayet.

Trin 3) Derefter går man vidre til det næste tal hvor der ikke allerede er et hak. Det er 5 (4 er der allered et hak i). Fra denne sætter man et hak henover alle multipla af 5: 10, 15, 20, 55, ... indtil man løber "ovenud" af arrayet.

... og sådan fortsætter man:

Trin 4) 6 er hallet af. 7 er det næste ...

Trin 5) 8 er hakket af, 9 er hakket af, 10 er hakket af, 11 er den næste ...

... og sådan fortsætter man ....

- til at man løber "ovenud" arrayet og ikke kan fortsætte mere.
Avatar billede arne_v Ekspert
18. december 2007 - 20:14 #17
sieve:

2 3 4 5 6 7 8 9 10

streg alle multipla af 2: 4, 6, 8, 10
streg alle multipla af 3: 6, 9

2, 3, 5 og 7 er tilbage

(det er ikke noedvendigt at strege multipla af 5 og 7 da de er stoerre end kvadratroden
af 10 og der er ingen grund til at strege multipla af noget der ikke er primtal)
Avatar billede gnukki Nybegynder
18. december 2007 - 20:18 #18
ja okay, jeg havde håbet lidt på at selv lave en funktion, der gjorde det og ikke bruge sieve... men det er måske en meget stor mundfuld?
Avatar billede nielle Nybegynder
18. december 2007 - 20:23 #19
Algoritmen er drønsimpel, og den burde du kunne lave uden de større problemer.
Avatar billede gnukki Nybegynder
18. december 2007 - 20:30 #20
Mit bedste eksempel er:
for(i=start;i<ulimit;i++){
            for(j=2;j<i;j++){
                u = i%j;
                if(u==0){
                    table[i] = 0;
                    break;                 
                }
            }
       
    }

Hvor start og ulimit er den nedre og øvre grænse for det interval, der skal søges efter primtal i. Men det er jo ikke den rigtigt algoritme. Jeg må indrømme, jeg ikke helt forstår hvad jeg skal lave om?
Avatar billede nielle Nybegynder
18. december 2007 - 20:37 #21
EoS starter altid fra 2 af. Du kan ikke starte andre steder, ellers giver den forkerte resultater.

Dernæst synes jeg at du skal glemme alt om den eksisterende kode, og kigge på beskivelserne i 18/12-2007 20:13:20 eller i 18/12-2007 20:14:33. Hvordan eftergøre du bedst dem med et array og to løkker.
Avatar billede nielle Nybegynder
18. december 2007 - 20:38 #22
Der skal slet ikke bruge % nogen steder, så hvs du får lyst til det, så er du på omveje. ;^)
Avatar billede gnukki Nybegynder
18. december 2007 - 20:42 #23
Hehe ja okay, jeg er forholdsvis ny indenfor programmering, hvis du ikke har bemærket det ;) men jeg har brug for lidt hjælp til at komme igang med at lave min egen algoritme
Avatar billede nielle Nybegynder
18. december 2007 - 20:47 #24
Mit forslag er at du starter med at prøve den manuelt på et ternet ark papit. Hvert tern er et af tallene.

Tilsammen udgør alle tallene så et array.
Avatar billede nielle Nybegynder
19. december 2007 - 18:01 #25
Kom du videre med denne her?
Avatar billede gnukki Nybegynder
19. december 2007 - 20:24 #26
Ikke ret meget, jeg kunne ikke lige komme frem til hvordan jeg får programmet til at udelukke alle multipla af 2 :/
Avatar billede nielle Nybegynder
19. december 2007 - 20:47 #27
Det gør du sådan (med en while-løkke):

    // Størrelsen på sien.
    const int maksTal = 100;

    // Initialisering af sien.
    char talFelt[maksTal+1];
    for (int tal = 2; tal <= maksTal; tal++)
        talFelt[tal] = ' ';

    // Fjern alle multpla af tallet 2.
    int tal = 2;  // Start med 2

    // Start ved første multipla af tallet.
    int afkrydsTal = tal + tal;

    // ... fortsæt med alle multipla indtil at vi løber ud over enden.
    while (afkrydsTal <= maksTal)
    {
        // Sæt kryds.
        talFelt[afkrydsTal] = 'X';

        // Tæl op til næste multipla,
        afkrydsTal += tal;
    }

    // Udskriv
    for (int tal = 2; tal <= maksTal; tal++)
    {
        if (talFelt[tal] == ' ')
            cout << tal << ' ';
    }
    cout << endl;

- eller sådan (med en for-løkke):

    // Størrelsen på sien.
    const int maksTal = 100;

    // Initialisering af sien.
    char talFelt[maksTal+1];
    for (int tal = 2; tal <= maksTal; tal++)
        talFelt[tal] = ' ';

    // Fjern alle multpla af tallet 2.
    int tal = 2;  // Start med 2

    // Start ved første multipla af tallet.
    for (int afkrydsTal = tal + tal; afkrydsTal <= maksTal; afkrydsTal += tal)
    {
        // Sæt kryds.
        talFelt[afkrydsTal] = 'X';
    }

    // Udskriv
    for (int tal = 2; tal <= maksTal; tal++)
    {
        if (talFelt[tal] == ' ')
            cout << tal << ' ';
    }
    cout << endl;
Avatar billede gnukki Nybegynder
19. december 2007 - 21:09 #28
mange tak,, jeg skal så tage din kode og indsætte i en ny løkke?
Avatar billede nielle Nybegynder
19. december 2007 - 21:10 #29
Den del hvor at man starter med 2 tallet, skal ind i en løkke som går vidre til 3 bagefter og gør det samme.
Avatar billede gnukki Nybegynder
19. december 2007 - 22:46 #30
Gider du lige forklare logikken i:
for (int afkrydsTal = tal + tal; afkrydsTal <= maksTal; afkrydsTal += tal)

:)
Avatar billede nielle Nybegynder
19. december 2007 - 23:18 #31
Ja da.

Vi skal ikke krydse af ud for tallet selv. Vi skal først starte fra det første multiplum:

afkrydsTal = tal+tal  (= 2*tal)

Vi skal fortsættt med at krydse af indtil at vi når ud over neden af der hvor sien går til:

afkrydsTal <= maksTal

Vi skal krydse af for hvert multiplum. Dvs når vi har krydet af ud for tallet afkrydsTal, så er det næste tal vi skal krydse af ved lig med afkrydsTal+tal.

afkrydsTal = afkrydsTal + tal

(hvilket kan skrives på den kortere form: "afkrydsTal += tal")

Håber at det var forståligt?
Avatar billede nielle Nybegynder
28. december 2007 - 21:45 #32
Har du helt opgivet denne her?
Avatar billede gnukki Nybegynder
04. januar 2008 - 20:22 #33
Hej nielle,

Jeg har overhovedet ikke opgivet det, jeg har bare haft meget arbejde her mellem jul og nytår, så har slet ikke fået set på det. Men det har jeg nu, og jeg forstår det må jeg sige, endelig :P

Du skal have mange tak for hjælpen :)
Gider du smide et svar?
Avatar billede nielle Nybegynder
05. januar 2008 - 08:24 #34
Skal arne_v ikke også smide et svar (18/12-2007 19:47:12) ?
Avatar billede arne_v Ekspert
06. januar 2008 - 04:58 #35
in case
Avatar billede gnukki Nybegynder
11. januar 2008 - 08:52 #36
Nu var I begge så behjælpelige så I får lov til at dele om pointene :) Men mange tak for hjælpen.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester