Hogyan ellenőrizhető, hogy egy szám Prime-e a Pythonban

Ez az oktatóanyag megtanítja Önnek, hogyan kell Python programot írni annak ellenőrzésére, hogy egy szám prímszámú-e vagy sem.

Ha valaha is részt vett kódolási teszteken, akkor találkozott a matematikai kérdéssel az elsődlegesség tesztjén vagy annak ellenőrzésére, hogy egy szám prím-e. A következő néhány percben pedig megtanulja, hogyan találja ki az optimális megoldást erre a kérdésre.

Ebben az oktatóanyagban a következőket teheti:

  • áttekinteni a prímszámok alapjait,
  • írjon Python kódot, hogy ellenőrizze, hogy egy szám prímszám-e, és
  • optimalizálja tovább, hogy O(√n) futásidejű algoritmust kapjon.

Mindehhez és még sok máshoz kezdjük.

Mi az a prímszám?

Kezdjük a prímszámok alapjainak áttekintésével.

A számelméletben egy n természetes számról azt mondják, hogy az prime ha pontosan két tényezője van: 1 és maga a szám (n). Emlékezzünk vissza az iskolai matematikából: az i számot az n szám tényezőjének mondjuk, ha i egyenlően osztja n-t. ✅

A következő táblázat felsorol néhány számot, azok összes tényezőjét, és azt, hogy prímszámúak-e.

nTényezők az elsődleges

A fenti táblázatból a következőket írhatjuk le:

  • 2 a legkisebb prímszám.
  • 1 minden szám tényezője.
  • Minden n szám önmagában is tényező.

Tehát 1 és n triviális tényezők bármely n számra. Egy prímszámnak pedig e kettőn kívül nem lehet más tényezője.

Ez azt jelenti, hogy amikor 2-ről n – 1-re lép, nem találhat olyan nem triviális tényezőt, amely maradék nélkül osztja n-t.

O(n) Algoritmus annak ellenőrzésére, hogy egy szám Prime-e a Pythonban

Ebben a részben formalizáljuk a fenti megközelítést Python-függvénnyel.

A Pythonban a range() objektum segítségével 2-től n – 1-ig minden számot végigcsikorgathat.

A Pythonban a range(start, stop, step) egy tartományobjektumot ad vissza. Ezután ismételheti a tartomány objektumot, hogy lépésenkénti lépésekben kapjon egy sorozatot az elejétől egészen a -1 megállításáig.

  A 11 legjobb AWS megfigyelő eszköz 2022-ben

Mivel szükségünk van a 2-től n-1-ig terjedő egész számokra, megadhatjuk a range(2, n)-t, és a for ciklussal együtt használhatjuk.

Íme, mit szeretnénk tenni:

  • Ha talál egy számot, amely n-t egyenletesen osztja el, maradék nélkül, azonnal megállapíthatja, hogy a szám nem prím.
  • Ha végigpörgette a számok teljes tartományát 2-től egészen n – 1-ig anélkül, hogy olyan számot talált volna, amely egyenletesen osztja n-t, akkor a szám prím.

Python függvény a prímszám ellenőrzéséhez

A fentiek felhasználásával a következőképpen definiálhatjuk az is_prime() függvényt.

def is_prime(n):
  for i in range(2,n):
    if (n%i) == 0:
      return False
  return True

Most elemezzük a fenti függvénydefiníciót.

  • A fenti is_prime() függvény egy n pozitív egész számot vesz fel argumentumként.
  • Ha talál egy tényezőt a megadott (2, n-1) tartományban, a függvény False értéket ad vissza – mivel a szám nem prímszám.
  • És igazat ad vissza, ha a teljes hurkon bejárja anélkül, hogy tényezőt találna.

Ezután hívjuk meg a függvényt argumentumokkal, és ellenőrizzük, hogy a kimenet helyes-e.

is_prime(2)
# True

is_prime(8)
# False

is_prime(9)
# False

is_prime(11)
# True

A fenti kimenetben azt látja, hogy 2 és 11 prím (a függvény True-t ad vissza). És 8 és 9 nem prímszám (a függvény False értéket ad vissza).

Az is_prime() Python függvény optimalizálása

Itt tehetünk egy kis optimalizálást. Vegye figyelembe a tényezők listáját az alábbi táblázatban.

Számtényezők 61, 2, 3, 6101, 2, 5, 10181, 2, 3, 6, 9, 18

Nos, láthatjuk, hogy n egyetlen tényezője, amely nagyobb n/2-nél, maga az n.

Tehát ez azt jelenti, hogy nem kell egészen n – 1-ig hurkolnia. Ehelyett csak n/2-ig futtathatja a ciklust.

Ha n/2-ig nem talál nem triviális tényezőt, akkor n/2-n túli tényezőt sem talál.

Most módosítsuk az is_prime() függvényt, hogy ellenőrizzük a (2, n/2) tartományban lévő tényezőket.

def is_prime(n):
  for i in range(2,int(n/2)):
    if (n%i) == 0:
      return False
  return True

Menjünk tovább, és ellenőrizzük a kimenetet néhány függvényhívással.

is_prime(9)
# False

is_prime(11)
# True

Annak ellenére, hogy úgy tűnhet, hogy optimalizáltunk, ez az algoritmus nem hatékonyabb, mint az előző a futásidejű összetettség szempontjából. Valójában mindkettő O(n) futásidejű bonyolultságú: arányos n értékével vagy lineáris n-ben.

  Mit jelent az about:blank Chrome/Firefox vagy Safari böngészőben?

Tudunk jobban csinálni? Igen!

▶️ Lépjen a következő szakaszra, hogy meghatározza, hogyan javíthatja a prímszámok tesztelésének időbonyolítását.

O(√n) algoritmus a prímszám ellenőrzésére a Pythonban

Előfordul, hogy egy szám tényezői párban fordulnak elő.

Ha a az n szám tényezője, akkor létezik olyan b tényező is, amelyre axb = n, vagy egyszerűen ab = n.

Ellenőrizzük ezt egy példán keresztül.

Az alábbi táblázat a 18-as szám párokban előforduló tényezőit mutatja. Ha szeretné, ellenőrizheti ugyanezt néhány további számnál is.

Azt is vegye figyelembe, hogy a √18 körülbelül 4,24.

Az (a, b) párokban előforduló tényezőkből pedig látható, hogy ha a kisebb, mint 4,24, akkor b nagyobb, mint 4,24 – ebben a példában (2, 18) és (3, 6).

18-as faktorok párban

Az alábbi ábra a 18 tényezőit mutatja a számegyenesen ábrázolva.

Ha az n szám történetesen tökéletes négyzet, akkor a = b = √n lesz az egyik tényező.

▶️ Nézd meg a 36-os faktorokat az alábbi táblázatban. Mivel 36 tökéletes négyzet, a = b = 6 az egyik tényező. Az összes többi faktorpárra (a, b) a < 6 és b > 6 érvényes.

36-os faktorok párban

Összefoglalva a következőket kapjuk:

  • Minden n szám felírható úgy, hogy n = axb
  • Ha n tökéletes négyzet, akkor a = b = √n.
  • És ha a < b, akkor a < √n és b > √n.
  • Egyébként ha a > b, akkor a > √n és b < √n.

Tehát ahelyett, hogy n/2-ig végigpörgetné az összes egész számot, dönthet úgy, hogy √n-ig fut. És ez sokkal hatékonyabb, mint az előző megközelítésünk.

Hogyan módosítsuk az is_prime()-t O(√n) algoritmusra

Folytassa a függvény optimalizálásával, hogy ellenőrizze a prímszámokat a Pythonban.

import math
def is_prime(n):
  for i in range(2,int(math.sqrt(n))+1):
    if (n%i) == 0:
      return False
  return True

Most elemezzük a fenti függvénydefiníciót:

  • Egy szám négyzetgyökének kiszámításához importáljuk a Python beépített matematikai modulját, és használjuk a math.sqrt() függvényt.
  • Mivel lehet, hogy n nem tökéletes négyzet, egész számba kell öntnünk. Az int(var) használatával a var-t int-be öntheti.
  • Annak érdekében, hogy megbizonyosodjunk arról, hogy valóban √n-ig ellenőrizzük, hozzáadunk egy plusz egyet, mivel a range() függvény alapértelmezés szerint kizárja a tartomány végpontját.
  Hogyan készíts Prisma stílusú iMessage matricákat a szelfikből

Az alábbi kódcella ellenőrzi, hogy az is_prime() függvényünk megfelelően működik-e.

is_prime(8)
# False

is_prime(15)
# False

is_prime(23)
# True

A következő részben készítsünk néhány egyszerű grafikont az O(n) és O(√n) vizuális megértéséhez.

O(n) és O(√n) vizuális összehasonlítása

▶️ Futtassa a következő kódrészletet egy választott Jupyter notebook környezetben.

import numpy as np
import seaborn as sns
import pandas as pd


n = 20

x = np.arange(n)
y1 = np.sqrt(x)
y2 = x
df = pd.DataFrame({"O(√n)":y1,"O(n)":y2})
sns.set_theme()
sns.lineplot(data = df)

A fenti részlet megmutatja, hogyan ábrázolhatja az n és √n görbéit egy értéktartományhoz.

  • A NumPy arange() függvényt használjuk számtömb létrehozására.
  • Ezután összegyűjtjük n és √n értékét 20-ig, de nem számítva egy pandas DataFrame.
  • Ezután ábrázoljuk a felhasználást seaborn vonalrajza() funkció.

Az alábbi ábrából láthatjuk, hogy √n lényegesen kisebb, mint n.

Most növeljük a tartományt 2000-re, és ismételjük meg a fenti lépéseket.

import numpy as np
import seaborn as sns
import pandas as pd


n = 2000

x = np.arange(n)
y1 = np.sqrt(x)
y2 = x
df = pd.DataFrame({"O(√n)":y1,"O(n)":y2})
sns.set_theme()
sns.lineplot(data = df)

A fenti diagramból arra következtethet, hogy az O(√n) algoritmus lényegesen gyorsabb, ha azt teszteli, hogy nagy szám prímszámú-e.

Íme egy gyors példa: a 2377 egy prímszám – ellenőrizze ezt!😀

Míg az O(n) megközelítés 2000 lépésből áll, az O(√n) algoritmus mindössze 49 lépésben segíthet a válasz megtalálásában.✅

Következtetés

⏳ És itt az ideje egy gyors összefoglalónak.

  • Annak ellenőrzésére, hogy egy szám prím-e, a naiv megközelítés az, hogy a (2, n-1) tartományban lévő összes számot végighurkoljuk. Ha nem talál n-t osztó tényezőt, akkor n prím.
  • Mivel az n n/2-nél nagyobb tényezője csak maga az n, dönthet úgy, hogy csak n/2-ig fut.
  • Mindkét fenti megközelítés időbonyolítása O(n).
  • Mivel egy szám tényezői párban fordulnak elő, csak √n-ig futhat. Ez az algoritmus sokkal gyorsabb, mint az O(n). A nyereség pedig észrevehető annak ellenőrzésekor, hogy egy nagy szám prím-e vagy sem.

Remélem, megérti, hogyan ellenőrizheti, hogy egy szám prím-e a Pythonban. Következő lépésként tekintse meg a Python programokról szóló oktatóanyagunkat a karakterlánc-műveletekkel kapcsolatban – ahol megtanulhatja, hogyan ellenőrizheti, hogy a karakterláncok palindromok, anagrammák és egyebek-e.

Találkozunk egy másik oktatóanyagban. Addig is jó kódolást!👩🏽‍💻