Vinnaren i pepparkakshustävlingen!
2020-08-20, 13:23
  #1645
Moderator
Neksnors avatar
Citat:
Ursprungligen postat av Ontogenes
Jag har nu skrivit ännu ett script som är tänkt att beräkna om ett tal är ett primtal eller inte. Det fungerar dock inte och jag skulle behöva hjälp med att reda ut diverse buggar. Här är koden:

Kod:
import math

number = 7
number_sqrt_ceil = math.ceil(math.sqrt(number))

if number > 1:
    for i in range(2, number_sqrt_ceil):
        if number_sqrt_ceil % i == 0:
            print(number, 'is NOT a prime number.')
            break
    else:
        print(number, 'IS a prime number!')

Output:



Istället för att ta mitt tal % i så tar jag istället kvadratroten ur mitt tal % i. Kvadratroten av 4 är 2, så i detta fall sker det som Blippster beskriver det vill säga att range(n, n) leder till en tom lista att iterera över vilket i sin tur leder till att mitt else-statement körs. Det är lite samma scenario som när number är 2.

När number är 6 så är kvadratroten av number 2.449489742783178, vilket avrundas uppåt till 3. I detta fall får jag alltså 3 % 2 som inte blir 0, vilket leder till att scriptet printar att även talet 6 är ett primtal, vilket är inkorrekt.

Det är ju ganska uppenbart att jag implementerat denna kvadratrotslösning på fel sätt. Några tips på hur jag kan lösa detta ?
Att testa huruvida ett heltal är ett primtal görs genom att försöka dela med mindre heltal. Hur ser själva testraden ut i din kod?
Citera
2020-08-20, 20:06
  #1646
Medlem
Ontogeness avatar
Citat:
Ursprungligen postat av Neksnor
Att testa huruvida ett heltal är ett primtal görs genom att försöka dela med mindre heltal. Hur ser själva testraden ut i din kod?

Vad menas med testrad? I koden från mitt förra inlägg så testar jag vad kvadratroten ur 7 är delbart med, och den första iterationen börjar med 2, så alltså kvadratroten ur 7 % 2, kvadratroten ur 7 är avrundat uppåt till 3, så 3 % 2. Om jag inte missförstått någonting så kunde jag ersätta talet 7 med kvadratroten ur 7, det var inte nödvändigt att testa upp till det talet.
Citera
2020-08-20, 21:24
  #1647
Moderator
vhes avatar
Citat:
Ursprungligen postat av Ontogenes
Vad menas med testrad? I koden från mitt förra inlägg så testar jag vad kvadratroten ur 7 är delbart med, och den första iterationen börjar med 2, så alltså kvadratroten ur 7 % 2, kvadratroten ur 7 är avrundat uppåt till 3, så 3 % 2. Om jag inte missförstått någonting så kunde jag ersätta talet 7 med kvadratroten ur 7, det var inte nödvändigt att testa upp till det talet.

Du har missförstått. Det är fortfarande talet du undersöker som du skall testa om det är delbart med de andra talen. Grejen med kvadratroten är att du aldrig behöver testa med faktorer som är större än talets kvadratrot. Du kan alltid veta med säkerhet att den lägsta faktorn i ett icke-primtal är lägre eller lika med talets kvadratrot.

(Bonusövning är att lura ut varför du kan veta det, men det har så klart inte med Python att göra).
Citera
2020-08-20, 22:52
  #1648
Moderator
Neksnors avatar
Citat:
Ursprungligen postat av Ontogenes
Vad menas med testrad? I koden från mitt förra inlägg så testar jag vad kvadratroten ur 7 är delbart med, och den första iterationen börjar med 2, så alltså kvadratroten ur 7 % 2, kvadratroten ur 7 är avrundat uppåt till 3, så 3 % 2. Om jag inte missförstått någonting så kunde jag ersätta talet 7 med kvadratroten ur 7, det var inte nödvändigt att testa upp till det talet.
Med testrad avsåg jag den kodrad där du kollar om talet är ett primtal, alltså raden
.
Där finns ett fel.
Citera
2020-08-23, 16:16
  #1649
Medlem
Ontogeness avatar
Citat:
Ursprungligen postat av vhe
Du har missförstått. Det är fortfarande talet du undersöker som du skall testa om det är delbart med de andra talen. Grejen med kvadratroten är att du aldrig behöver testa med faktorer som är större än talets kvadratrot. Du kan alltid veta med säkerhet att den lägsta faktorn i ett icke-primtal är lägre eller lika med talets kvadratrot.

(Bonusövning är att lura ut varför du kan veta det, men det har så klart inte med Python att göra).

Citat:
Ursprungligen postat av Neksnor
Med testrad avsåg jag den kodrad där du kollar om talet är ett primtal, alltså raden
.
Där finns ett fel.

Jag tror att jag förstår. Jag ska ta mitt tal % talet i kvadratrot, alltså ska min iterator ha en range mellan 2 och talet i kvadratrot?
Citera
2020-08-23, 18:28
  #1650
Moderator
Neksnors avatar
Citat:
Ursprungligen postat av Ontogenes
Jag tror att jag förstår. Jag ska ta mitt tal % talet i kvadratrot, alltså ska min iterator ha en range mellan 2 och talet i kvadratrot?
Iteratorn är OK, den ska gå från 2 till number_sqrt_ceil.
Men testraden, vad ska den göra, alltså vad går själva testet ut på?
Citera
2020-08-24, 13:26
  #1651
Medlem
Ontogeness avatar
Citat:
Ursprungligen postat av Neksnor
Iteratorn är OK, den ska gå från 2 till number_sqrt_ceil.
Men testraden, vad ska den göra, alltså vad går själva testet ut på?

Testraden bör exekvera number % iterator, där iterator har range(2, number_sqrt_ceil), alltså ett omfång från 2 till kvadratroten ur number avrundat uppåt till närmsta heltal. Detta är min kod hittills:

Kod:
import math

number = 7
number_sqrt_ceil = math.ceil(math.sqrt(number))

if number > 1:
    for i in range(2, number_sqrt_ceil):
        if number % i == 0:
            print(number, 'is NOT a prime number.')
            break
    else:
        print(number, 'IS a prime number!')

I början så missförstod jag hela principen med att använda kvadratroten ur det tal man vill testa, men nu tror jag att jag fattat grejen. Jag ska ersätta number som iterator med kvadratroten ur number, så att jag inte behöver testa med tal i onödan.

Koden ovan är dock rätt buggig fortfarande. Här är min output:

Citat:
0 = NULLL
1 = NULL
2 = PRIME
3 = PRIME
4 = PRIME (inkorrekt)
5 = PRIME
6 = NOT PRIME
7 = PRIME
8 = NOT PRIME
9 = PRIME (inkorrekt)
10 = NOT PRIME

Koden är inte lika buggig som sist men programmet påstår dock fortfarande att 4 och 9 är primtal vilket inte är fallet.

Om vi i ett försök att debugga börjar med vad som händer när number är 4 så har jag kommit fram till följande:

Om number är 4 så är kvadratroten ur number 2, men detta visas som en float istället för en integer (2.0 istället för 2) om man bara kör print(math.sqrt(number)), men i och med att jag avrundar alla tal uppåt med math.ceil()-funktionen så blir min float en integer (2 alltså). Vi fortsätter i koden...

4 är större än 1 så koden fortsätter köras. Min for-loop körs med omfånget 2 till number_sqrt_ceil vilket i detta fall blir 2. Min range har alltså omgången 2 till 2 vilket som Blippster poängterat innebär en tom lista att iterera över vilket leder till att min else-sats körs som printar att talet är ett primtal.

Detta är min teori om varför koden printar att talet 4 är ett primtal, stämmer detta eller har jag fått det helt om bakfoten?

När det kommer till talet 9 så blir kvadratroten ur number 3. I min for-loop får jag då en range mellan 2 till 3, och i den första iterationen körs 9 % 2 vilket inte blir 0, är det därför min else-sats körs? Eller jag är lite osäker kring vad som händer just i detta scenario...
Citera
2020-08-24, 14:09
  #1652
Moderator
Neksnors avatar
Citat:
Ursprungligen postat av Ontogenes
Testraden bör exekvera number % iterator, där iterator har range(2, number_sqrt_ceil), alltså ett omfång från 2 till kvadratroten ur number avrundat uppåt till närmsta heltal. Detta är min kod hittills:

Kod:
import math

number = 7
number_sqrt_ceil = math.ceil(math.sqrt(number))

if number > 1:
    for i in range(2, number_sqrt_ceil):
        if number % i == 0:
            print(number, 'is NOT a prime number.')
            break
    else:
        print(number, 'IS a prime number!')

I början så missförstod jag hela principen med att använda kvadratroten ur det tal man vill testa, men nu tror jag att jag fattat grejen. Jag ska ersätta number som iterator med kvadratroten ur number, så att jag inte behöver testa med tal i onödan.

Koden ovan är dock rätt buggig fortfarande. Här är min output:



Koden är inte lika buggig som sist men programmet påstår dock fortfarande att 4 och 9 är primtal vilket inte är fallet.

Om vi i ett försök att debugga börjar med vad som händer när number är 4 så har jag kommit fram till följande:

Om number är 4 så är kvadratroten ur number 2, men detta visas som en float istället för en integer (2.0 istället för 2) om man bara kör print(math.sqrt(number)), men i och med att jag avrundar alla tal uppåt med math.ceil()-funktionen så blir min float en integer (2 alltså). Vi fortsätter i koden...

4 är större än 1 så koden fortsätter köras. Min for-loop körs med omfånget 2 till number_sqrt_ceil vilket i detta fall blir 2. Min range har alltså omgången 2 till 2 vilket som Blippster poängterat innebär en tom lista att iterera över vilket leder till att min else-sats körs som printar att talet är ett primtal.

Detta är min teori om varför koden printar att talet 4 är ett primtal, stämmer detta eller har jag fått det helt om bakfoten?

När det kommer till talet 9 så blir kvadratroten ur number 3. I min for-loop får jag då en range mellan 2 till 3, och i den första iterationen körs 9 % 2 vilket inte blir 0, är det därför min else-sats körs? Eller jag är lite osäker kring vad som händer just i detta scenario...
Angående number=4, hur funkar range(x,y)?
Testas alla heltal inklusive eller exklusive x och y?
Själva testraden ser helt ok ut nu.
Citera
2020-08-24, 14:12
  #1653
Medlem
Ontogeness avatar
Citat:
Ursprungligen postat av Neksnor
Angående number=4, hur funkar range(x,y)?
Testas alla heltal inklusive eller exklusive x och y?
Själva testraden ser helt ok ut nu.

När number är 4 så är min range(2, 2) vilket innebär att for-loopen inte körs, så jag funderar på om jag får hårdkoda en lösning för just talet 4. Det jag inte riktigt har samma koll på är vad som egentligen försiggår när number är 9.
Citera
2020-08-24, 14:20
  #1654
Moderator
Neksnors avatar
Citat:
Ursprungligen postat av Ontogenes
När number är 4 så är min range(2, 2) vilket innebär att for-loopen inte körs, så jag funderar på om jag får hårdkoda en lösning för just talet 4. Det jag inte riktigt har samma koll på är vad som egentligen försiggår när number är 9.
Jag, som inte kan python, gissar att du finner lösningen genom att läsa dokumentationen för range().
Citera
2020-08-24, 14:29
  #1655
Medlem
Citat:
Ursprungligen postat av Ontogenes
När number är 4 så är min range(2, 2) vilket innebär att for-loopen inte körs, så jag funderar på om jag får hårdkoda en lösning för just talet 4. Det jag inte riktigt har samma koll på är vad som egentligen försiggår när number är 9.
Problemet är att range-funktionen ej inkluderar stop värdet. Du kommer få problem med din lösning för alla tal som bildas av kvadraten av ett primtal (dvs 4, 9, 25 etc)
Om du tar talet 49 (7 * 7) så kommer din range funtion att skapa sekvensen (2, .., 5, 6) dvs talet 7 kommer inte finnas med. Så du kommer inte testa mot just 7 som är den enda primtalsfaktorn i 49.
Så ändra din range-funktion till att inkludera även det sista värdet.
Sedan tycker jag du borde kolla på lite olika algoritmer för att hitta primtal för att kunna snygga till lösningen.
Citera
2020-08-24, 14:32
  #1656
Medlem
Ontogeness avatar
Citat:
Ursprungligen postat av Neksnor
Jag, som inte kan python, gissar att du finner lösningen genom att läsa dokumentationen för range().

Detta är redan fastställt! Blippster skrev tidigare i tråden att om range()-funktionen har samma tal som start och stoppvärde så körs inte for-loopen och det är därför else-satsen körs i min kod. Nu ser min kod ut såhär:

Kod:
import math

number = 7
number_sqrt_ceil = math.ceil(math.sqrt(number))

if number == 0:
	print(number, 'is not a prime number. A prime number has to be greater than 1.')

if number == 1:
	print(number, 'is not a prime number. A prime number has to be greater than 1.')

if number > 1:
	for i in range(2, number_sqrt_ceil):
		if number % i == 0:
			print(number, 'is not a prime number.')
			break
	else:
		print(number, 'is a prime number!')

Jag har testat koden upp till 20 nu och den fungerar bra, bortsett från talen 4 och 9. När det kommer till talet 4 så undrar jag snarare hur jag bör implementera en lösning till detta bugg, medan jag i fallet där talet är 9 inte riktigt förstår mekanismerna bakom varför det inte fungerar, om du fattar.

Vid den första iterationen (när talet är 9) så får vi 9 % 2 vilket inte blir 0, sedan får vi 9 % 3 vilket blir 0 och därför tycker jag att det borde stå att 9 inte är ett primtal, men det är tyvärr inte det som sker.

Okej nevermind, jag har löst bugget!!! När range()-funktionen körs så inkluderas inte stoppvärdet, 3 i det fallet att number är 9 det vill säga. Den kör då bara en iteration med 9 % 2 vilket inte blir 0, vilket resulterar i att programmet påstår att 9 är ett primtal.

En rimlig lösning borde vara att modifiera range()-funktionen till att även inkludera stoppvärdet, så att mitt omfång hamnar på 2 till 4 om number är 9 till exempel, vilket leder till att en andra iteration där 9 % 3 blir 0 kommer att köras. Någon som vet hur jag kan göra detta? Kan jag köra typ range(2, (number_sqrt_ceil) +1)?
Citera

Stöd Flashback

Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!

Stöd Flashback