C# Hitta alla primtal mellan 1 och talet som anges som parameter

Permalänk
Medlem
Skrivet av Ralleballe:

Fundera på var du ökar i1 i första for-loopen...

För övrigt brukar i, j användas om man har fler for-loopar, eller iaf två på varandra följande bokstäver.

Gjorde det, kom fram till att num inte ska ökas i första for-loopen eller hur? Ändrade till i1++ istället. Om jag nu matar in 100 så skriver den ut 100 i consolen runt 100 ggr. Något du kan hjälpa mig med?

Permalänk
Medlem
Skrivet av Teknocide:

Andra for-loopen har fortfarande fel i loop-villkoret. Det står nu: loopa så länge i2 är större än kvadratroten av num.

Tänk också på att num bara representerar det sista talet du vill testa: din yttre loop är tänkt att representera mängden 1 till num

ps: du är nära nu.

Vet inte hur jag ska göra så att den testar 1-numret man matar in. Behöver hjälp hur jag ska kunna göra så att num representerar mängden 1 till numret man matar in.

Permalänk
Medlem

Det finns lite egenskaper hos tal som inte är primtal som går att använda för att snabba upp sökandet.

Det finns ett lemma som går något i stil med "Alla tal är ett primtal eller en produkt av primtal"

Så din algoritm borde vara något i stil med

x: en lista av primtal

x <- [2] (börja med en lista med bara 2 i)
for(i = 3 < max, i++) (börja iterare på 3){
isPrime <- true;
foreach(x' in x){ (för alla primtal i listan)
if(i % x' == 0){
ifPrime <- false
break; //om talet ej är prima, avbryt
}
}
if(isPrime)
{
x <- x:[i] //lägg till i till primtalslistan.
}
}

Permalänk
Medlem
Skrivet av cp_:

Det finns lite egenskaper hos tal som inte är primtal som går att använda för att snabba upp sökandet.

Det finns ett lemma som går något i stil med "Alla tal är ett primtal eller en produkt av primtal"

Så din algoritm borde vara något i stil med

x: en lista av primtal

x <- [2] (börja med en lista med bara 2 i)
for(i = 3 < max, i++) (börja iterare på 3){
isPrime <- true;
foreach(x' in x){ (för alla primtal i listan)
if(i % x' == 0){
ifPrime <- false
break; //om talet ej är prima, avbryt
}
}
if(isPrime)
{
x <- x:[i] //lägg till i till primtalslistan.
}
}

Skulle gärna vilja hålla mig till en algoritmen jag har, bryr mig inte så mycket om hur fort det går. Vet du hur jag kan få num att representera 1-talet man sätter som tak?

Permalänk
Medlem
Skrivet av kempes:

Skulle gärna vilja hålla mig till en algoritmen jag har, bryr mig inte så mycket om hur fort det går. Vet du hur jag kan få num att representera 1-talet man sätter som tak?

num representerar ju redan det inskrivna värdet. Det är din yttre for-loop som representerar alla primtal mellan 1 och num

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av Teknocide:

num representerar ju redan det inskrivna värdet. Det är din yttre for-loop som representerar alla primtal mellan 1 och num

Hur ser det ut nu då?

int num; Console.WriteLine("Mata in nummer: "); num = Convert.ToInt32(Console.ReadLine()); for (int i = 1; i < num; i++) { for (int j = i; j < Math.Sqrt(num); j++) { if (num % j != 0) { Console.WriteLine(j); } } }

Permalänk
Medlem
Skrivet av kempes:

Hur ser det ut nu då?

int num; Console.WriteLine("Mata in nummer: "); num = Convert.ToInt32(Console.ReadLine()); for (int i = 1; i < num; i++) { for (int j = i; j < Math.Sqrt(num); j++) { if (num % j != 0) { Console.WriteLine(j); } } }

Det är fortfarande fel i din inre loop. Bland annat ska utskriften komma i den yttre loopen, du loopar fel i den inre, du testar fel variabel och du behöver en variabel till för att hålla koll på om den inre loopen avgjorde att du hade ett primtal eller ej.

Det känns som om du gör ändringar på måfå. Förstår att du börjar bli less på detta nu men ta ett steg tillbaka och fråga din lärare om råd.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av Teknocide:

Det är fortfarande fel i din inre loop. Bland annat ska utskriften komma i den yttre loopen, du loopar fel i den inre, du testar fel variabel och du behöver en variabel till för att hålla koll på om den inre loopen avgjorde att du hade ett primtal eller ej.

Det känns som om du gör ändringar på måfå. Förstår att du börjar bli less på detta nu men ta ett steg tillbaka och fråga din lärare om råd.

Eftersom att jag är väldigt ny i C# så förstår jag inte alltid vad du menar, hur jag ska göra saker osv. De är inte alltid lika självklart för mig som för dig. Förstår att du antagligen börjar tröttna på mitt tjat om den här tråden. Frågade faktiskt min lärare om råd/hjälp idag, gjorde mig dock inte så mycket klokare, du ser ju vad som ändrats i koden, det var de hon gjorde. Verkade inte som hon visste hur man skulle göra, då hon var tvungen och tänka i ca 10 minuter, detta var sedan vad hon hade kommit fram till och sa att jag skulle fundera på.

Permalänk
Medlem
Skrivet av kempes:

Eftersom att jag är väldigt ny i C# så förstår jag inte alltid vad du menar, hur jag ska göra saker osv. De är inte alltid lika självklart för mig som för dig. Förstår att du antagligen börjar tröttna på mitt tjat om den här tråden. Frågade faktiskt min lärare om råd/hjälp idag, gjorde mig dock inte så mycket klokare, du ser ju vad som ändrats i koden, det var de hon gjorde. Verkade inte som hon visste hur man skulle göra, då hon var tvungen och tänka i ca 10 minuter, detta var sedan vad hon hade kommit fram till och sa att jag skulle fundera på.

Kikade lite på det du skrivit och mitt huvudtips till att förstå är att kommentera vad du gör i din kod, på så sätt är det lättare att förstå vad som går fel.
Tänk på att ett tal är ett primtal om det enbart är jämnt delbart med sig själv och med ett men ger en rest i alla andra fall.
Som det har nämnt tidigare i tråden räcker det egentligen att testa ett tal mot alla andra primtal mindre än dess rot, detta skulle bli effektivare men känns inte direkt nödvändigt i ditt fall då det viktigaste nu är att fokusera på att förstå det man gör.

Kan ge två exempel att fundera på när du utformar din algoritm, säg att du vill kolla om 5 och 6 är primtal.
Först testar du 5, eftersom 5%2, 5%3, 5%4 alla är skilda från noll betyder det att det inte finns något tal mindre än 5 som delar det jämnt ut, altså ett primtal, samma experiement med 6 ger att det inte är ett primtal då 6%2 och 6%3 är lika med noll.
kort sagt, har du ett heltal n skall samtliga divisioner med heltal mellan 2 och n-1 ge en rest för att det skall vara ett primtal, hoppas det tankesättet kan få dig på rätt spår utan att avslöja för mycket

Permalänk
Medlem
Skrivet av kempes:

Eftersom att jag är väldigt ny i C# så förstår jag inte alltid vad du menar, hur jag ska göra saker osv. De är inte alltid lika självklart för mig som för dig. Förstår att du antagligen börjar tröttna på mitt tjat om den här tråden. Frågade faktiskt min lärare om råd/hjälp idag, gjorde mig dock inte så mycket klokare, du ser ju vad som ändrats i koden, det var de hon gjorde. Verkade inte som hon visste hur man skulle göra, då hon var tvungen och tänka i ca 10 minuter, detta var sedan vad hon hade kommit fram till och sa att jag skulle fundera på.

Jag gillar din envishet

Vi skulle kunna testa en annan approach, skita i alla optimeringar (kvadratrötter och fans moster) och bryta ner problemet i mindre, logiska bitar. Backtracka lite och reda ut vissa grejer. Är du med?

Till att börja med vill jag definiera vad ett primtal är. sv.wikipedia.org definierar ett primtal så här:

Citat:

Ett primtal är ett heltal p, som är större än 1 och vars enda delare är ±1 och ±p.

Det vill säga, för att godtyckligt tal n skall vara ett primtal gäller att

  1. n är större än 1

  2. n inte går att dela jämnt med något tal mellan 2 och n-1, såvida n inte är 2:

  3. då 2 bara går att dela med sig själv och med 1 är 2 ett primtal

Punkt 1 är enkel att formulera: om n är större än 1 kan n vara ett primtal

if (n > 1) { ... testa om n är jämnt delbart med något av talen mellan 2 och n-1 } else { ... n kan inte vara ett primtal om det är lika med eller mindre än 1. }

För att se om ett tal är jämnt delbart med ett annat kollar vi vad resten blir av en division. Jag vill minnas att detta var något man höll på med i slutet av lågstadiet och sedan glömde bort när man gick över till att räkna med decimaler, liggande stolar och andra konstigheter.

För att få fram resten av en division använder vi oss av modulo-operatorn, vilken i programmeringssammanhang vanligtvis är ett procenttecken. Om det inte finns någon rest efter en division har man en kvot som är ett heltal, och om kvoten är ett heltal har divisionen gått jämnt ut. Det är av den enkla anledningen som man testar om resultatet av en modulo-operation är lika med 0.

if (n % ??? == 0) { ... }

Frågetecknena representerar ett godtyckligt tal mellan 2 och n-1. Om resultatet av operationen [n % ???] är 0 har divisionen gått jämnt ut och n är inte ett primtal.

Om man var envis skulle man kunna testa ett primtal så här:

int n = 5; if (n > 1 && n % 2 != 0 && n % 3 != 0 && n % 4 != 0) { Console.WriteLine(n + " är ett primtal!"); } else { Console.WriteLine("Nix, " + n + " är inget primtal."); }

Som du kan se skulle det bli ganska tråkigt att skriva if-satsen när n är ett större tal, säg runt 42 eller så. För att göra livet lättare använder vi en for-loop:

for (int i = 2; i < n - 1; i++) { ... om resultatet av [n % i] == 0 är n inte ett primtal }

For-loopar är fula och svårlästa men väldigt praktiska. Något som däremot bara är praktiskt är metoder. Det är snudd på överkurs men i just detta fall, när vi letar efter ett sätta att hitta primtal, är en metod helt oslagbar.

I grund och botten ser en metod ut så här:

returtyp Metodnamn(parametertyp parameternamn) { ... metod-kod }

  • returtypen är den typ av värde som metoden kommer returneras. Exempel på detta är string, int och bool, som denna metod kommer returnera.

  • parametertyp är samma sak fast åt andra hållet och specifierar vad metoden kan arbeta med för värde. Eftersom vi vill testa ett heltal använder vi typen int

Metodnamn är ett valfritt ord som börjar med en bokstav eller underscore och kan följas av siffror, bokstäver eller underscore. Exempel på tillåtna namn är Glass, U2, KamelFodral och _Skriv_Inte_Så_Här. Otillåtna namn är 42IsANumber, 5+5=11 och ?!OMG?!

bool IsPrime(int n) { om n > 1: testa om n är jämnt delbart med mängden [2 -> n-1] annars: return false; }

Det du ser ovan är pseudokod; "halvkod" som beskriver kod. Det som är fetmarkerat är riktig C#-kod. Sista raden, return false;, säger att metoden IsPrime returnerar bool-värdet false om n inte är ett primtal.

Genom att pussla med de exempel som getts kan du faktiskt få en helt fungerande IsPrime-metod som löser 95 % av uppgiften åt dig. Det slutgiltiga steget är att använda IsPrime-metoden i ännu en for-loop för att testa alla tal mellan 1 och det av användaren angivna talet num (som du redan har lyckats läsa in i tidigare kod-exempel).

Ett riktigt trevligt program att ha till hands när man sitter och testar C#-kod är LINQPad. Namnet är ganska missvisande då det går att använda till mycket mer än LINQ. Jag rekommenderar att du laddar ner det och labbar lite med det som tagits upp här. Skapa en ny "query" och tryck på CTRL + 3 för att få en liten main-metod där du kan testa kod.

Visa signatur

Kom-pa-TI-bilitet

Permalänk
Medlem
Skrivet av Teknocide:

Jag gillar din envishet

Vi skulle kunna testa en annan approach, skita i alla optimeringar (kvadratrötter och fans moster) och bryta ner problemet i mindre, logiska bitar. Backtracka lite och reda ut vissa grejer. Är du med?

Till att börja med vill jag definiera vad ett primtal är. sv.wikipedia.org definierar ett primtal så här:

Det vill säga, för att godtyckligt tal n skall vara ett primtal gäller att

  1. n är större än 1

  2. n inte går att dela jämnt med något tal mellan 2 och n-1, såvida n inte är 2:

  3. då 2 bara går att dela med sig själv och med 1 är 2 ett primtal

Punkt 1 är enkel att formulera: om n är större än 1 kan n vara ett primtal

if (n > 1) { ... testa om n är jämnt delbart med något av talen mellan 2 och n-1 } else { ... n kan inte vara ett primtal om det är lika med eller mindre än 1. }

För att se om ett tal är jämnt delbart med ett annat kollar vi vad resten blir av en division. Jag vill minnas att detta var något man höll på med i slutet av lågstadiet och sedan glömde bort när man gick över till att räkna med decimaler, liggande stolar och andra konstigheter.

För att få fram resten av en division använder vi oss av modulo-operatorn, vilken i programmeringssammanhang vanligtvis är ett procenttecken. Om det inte finns någon rest efter en division har man en kvot som är ett heltal, och om kvoten är ett heltal har divisionen gått jämnt ut. Det är av den enkla anledningen som man testar om resultatet av en modulo-operation är lika med 0.

if (n % ??? == 0) { ... }

Frågetecknena representerar ett godtyckligt tal mellan 2 och n-1. Om resultatet av operationen [n % ???] är 0 har divisionen gått jämnt ut och n är inte ett primtal.

Om man var envis skulle man kunna testa ett primtal så här:

int n = 5; if (n > 1 && n % 2 != 0 && n % 3 != 0 && n % 4 != 0) { Console.WriteLine(n + " är ett primtal!"); } else { Console.WriteLine("Nix, " + n + " är inget primtal."); }

Som du kan se skulle det bli ganska tråkigt att skriva if-satsen när n är ett större tal, säg runt 42 eller så. För att göra livet lättare använder vi en for-loop:

for (int i = 2; i < n - 1; i++) { ... om resultatet av [n % i] == 0 är n inte ett primtal }

For-loopar är fula och svårlästa men väldigt praktiska. Något som däremot bara är praktiskt är metoder. Det är snudd på överkurs men i just detta fall, när vi letar efter ett sätta att hitta primtal, är en metod helt oslagbar.

I grund och botten ser en metod ut så här:

returtyp Metodnamn(parametertyp parameternamn) { ... metod-kod }

  • returtypen är den typ av värde som metoden kommer returneras. Exempel på detta är string, int och bool, som denna metod kommer returnera.

  • parametertyp är samma sak fast åt andra hållet och specifierar vad metoden kan arbeta med för värde. Eftersom vi vill testa ett heltal använder vi typen int

Metodnamn är ett valfritt ord som börjar med en bokstav eller underscore och kan följas av siffror, bokstäver eller underscore. Exempel på tillåtna namn är Glass, U2, KamelFodral och _Skriv_Inte_Så_Här. Otillåtna namn är 42IsANumber, 5+5=11 och ?!OMG?!

bool IsPrime(int n) { om n > 1: testa om n är jämnt delbart med mängden [2 -> n-1] annars: return false; }

Det du ser ovan är pseudokod; "halvkod" som beskriver kod. Det som är fetmarkerat är riktig C#-kod. Sista raden, return false;, säger att metoden IsPrime returnerar bool-värdet false om n inte är ett primtal.

Genom att pussla med de exempel som getts kan du faktiskt få en helt fungerande IsPrime-metod som löser 95 % av uppgiften åt dig. Det slutgiltiga steget är att använda IsPrime-metoden i ännu en for-loop för att testa alla tal mellan 1 och det av användaren angivna talet num (som du redan har lyckats läsa in i tidigare kod-exempel).

Ett riktigt trevligt program att ha till hands när man sitter och testar C#-kod är LINQPad. Namnet är ganska missvisande då det går att använda till mycket mer än LINQ. Jag rekommenderar att du laddar ner det och labbar lite med det som tagits upp här. Skapa en ny "query" och tryck på CTRL + 3 för att få en liten main-metod där du kan testa kod.

Tack för all hjälp. Har pratat mer med min lärare och hon tyckte att det var en svårt uppgift att göra, vi satt i ca 30 min och kunde in få ihop den själva. Dock var det 2 andra i klassen som googlade och kopierade en kod, de fick den att funka. Hon sa att jag inte skulle oroa mig för mitt betyg, eftersom att det var ett bra försök jag hade gjort.

Tack för all hjälp, är mycket tacksam!