Logo des digitalen Schulbuchs inf-schule.de. Schriftzug in Zustandsübergangsdiagramm eines endlichen Automaten.

Ein Baustein für Primzahltests

Verhaltensbeschreibung

Ziel ist es weiterhin, eine Funktion zu entwickeln, mit der man natürliche Zahlen daraufhin überprüfen kann, ob sie Primzahlen sind oder nicht.

<Black-Box-Diagramm><Funktionsname>istPrimzahl</Funktionsname><Übergaben><Übergabe><Wert>13</Wert><Variable>n</Variable><Typ>int</Typ></Übergabe></Übergaben><Rückgabe><Typ>boole</Typ><Wert>true</Wert></Rückgabe></Black-Box-Diagramm>

Die Funktion istPrimzahl verarbeitet eine Zahl vom Typ int (d.h. eine ganze Zahl) und liefert als Ergebnis einen Wert vom Typ bool (d.h. einen der beiden Wahrheitswerte True oder False) zurück.

Ein erster Implementierungsversuch

Hier eine Implementierung zu einem der Primzahltestalgorithmen aus dem letzten Abschnitt.

def istPrimzahl(n):
    prim = True
    k = 2
    while k*k <= n and prim:
        if n % k == 0:
            prim = False
        k = k+1
    return prim

Aufgabe 1

Teste die Funktion mit mehreren Testaufrufen. Ist alles ok?

>>> istPrimzahl(13)
True
>>> istPrimzahl(15)
...
>>> istPrimzahl(7)
...
>>> istPrimzahl(551)
...
>>> istPrimzahl(2)
...
>>> istPrimzahl(1)
...
>>> istPrimzahl(0)
...

Eine Implementierung mit Testfällen

Eine implementierte Funktion sollte immer gründlich getestet werden. Meist reicht dazu nicht nur ein Testfall. Vielmehr muss man unterschiedlichste Situationen mit Testfällen abdecken. Hierzu zählen insbesondere die Randfälle.

Beim Testen kommt es darauf an , die Erwartungen, die man an eine Funktion hat, mit dem tatsächlichen Verhalten abzugleichen. Eine gute Strategie ist es, die Erwartungen vorab schon einmal zu dokumentieren.

Python bietet eine Möglichkeit, Verhaltensbeschreibungen in Form von Testfällen in die Implementierung von Funktionen zu integrieren und diese Testfälle dann automatisiert zu überprüfen. Mehr über dieses Thema findest du im Abschnitt Verhalten beschreiben und testen.

def istPrimzahl(n):
    
    """
    Verhalten:
    Übergabe: natürliche Zahl n
    Rückgabe: True, falls n eine Primzahl ist
              False, sonst
    Testfälle:
    >>> istPrimzahl(13)
    True
    >>> istPrimzahl(15)
    False
    >>> istPrimzahl(7)
    True
    >>> istPrimzahl(551)
    False
    >>> istPrimzahl(2)
    True
    >>> istPrimzahl(1)
    False
    >>> istPrimzahl(0)
    False
    """
    
    prim = True
    k = 2
    while k*k <= n and prim:
        if n % k == 0:
            prim = False
        k = k+1
    return prim

if __name__ == "__main__":
    from doctest import testmod
    testmod(verbose=True)

Wenn man diese Funktionsdefinition ausführt, dann werden die Testfälle überprüft und man erhält genaue Rückmeldungen.

>>> 
Trying:
    istPrimzahl(13)
Expecting:
    True
ok
Trying:
    istPrimzahl(15)
Expecting:
    False
ok
Trying:
    istPrimzahl(7)
Expecting:
    True
ok
Trying:
    istPrimzahl(551)
Expecting:
    False
ok
Trying:
    istPrimzahl(2)
Expecting:
    True
ok
Trying:
    istPrimzahl(1)
Expecting:
    False
**********************************************************************
File "...", line 19, in __main__.istPrimzahl
Failed example:
    istPrimzahl(1)
Expected:
    False
Got:
    True
Trying:
    istPrimzahl(0)
Expecting:
    False
**********************************************************************
File "...", line 21, in __main__.istPrimzahl
Failed example:
    istPrimzahl(0)
Expected:
    False
Got:
    True
1 items had no tests:
    __main__
**********************************************************************
1 items had failures:
   2 of   7 in __main__.istPrimzahl
7 tests in 2 items.
5 passed and 2 failed.
***Test Failed*** 2 failures.

Aufgabe 2

(a) Probiere das selbst aus. Wie sind die Rückmeldungen von Python zu deuten?

(b) Verbessere die Funktionsdefinition so, dass alle Testfälle den Test bestehen. Tipp: Du musst zu Beginn eine zusätzliche Fallunterscheidung vorsehen.

Verwendung einer Funktion als Bausteins

Eine gut getestete Funktionsdefinition kann man bei weiterführenden Problemlösungen als Baustein verwenden. Hier ein Beispiel, bei dem überprüft werden soll, ob ein Primzahlzwilling vorliegt.

Der Funktionsbaustein wird hier mit einer import-Anweisung in das Programm integriert. Die importierte Funktion istPrimzahl befindet sich hier in der Datei primzahltest.py.

from primzahltest import istPrimzahl

def istPrimzahlzwilling(n):

    """
    Verhalten:
    Übergabe: natürliche Zahl n
    Rückgabe: True, falls n und n+2 eine Primzahl ist
              False, sonst
    Testfälle:
    >>> istPrimzahlzwilling(11)
    True
    >>> istPrimzahlzwilling(13)
    False
    >>> istPrimzahlzwilling(15)
    False
    """

    if istPrimzahl(n):
        if istPrimzahl(n+2):
            ergebnis = True
        else:
            ergebnis = False
    else:
        ergebnis = False
    return ergebnis

if __name__ == "__main__":
    from doctest import testmod
    testmod(verbose=True)

Aufgabe 3

(a) Teste selbst, indem du die Funktionsdefinition ausführst.

(b) Die geschachtelte Fallunterscheidung kann man vermeiden, wenn man einen logischen Operator benutzt. Informiere dich im Abschnitt Wahrheitswerte und Bedingungen über logische Operatoren.

Aufgabe 4

Entwickle eine Funktionsdefinition für eine Funktion naechstePrimzahl. Benutze die Funktion istPrimzahl als Baustein.

from primzahltest import istPrimzahl

def naechstePrimzahl(n):

    """
    Verhalten:
    Übergabe: natürliche Zahl n
    Rückgabe: die nächste Primzahl, die größer oder gleich n ist
    Testfälle:
    >>> naechstePrimzahl(5)
    5
    >>> naechstePrimzahl(20)
    23
    >>> naechstePrimzahl(0)
    2
    """

    ...

if __name__ == "__main__":
    from doctest import testmod
    testmod(verbose=True)
X

Fehler melden

X

Suche