Hallo,
'time' wird importiert aber nicht genutzt.
Auf Modulebene (der Code ohne Einrückungen) darf kein ausführbarer Code stehen. Hier werden nur Klassen, Funktionen und Konstanten definiert. Es gibt eine Ausnahme, das ist eine 'if'-Abfrage als Einstiegspunkt in die 'main'-Funktion. Darin sollte dein Programm starten und von dort werden weitere Funktionen aufgerufen, Argumente übergeben und wieder entgegen genommen.
Gewöhne dir gleich an sprechende Namen zu verwenden und keine Abkürzungen. Das ist in der Mathematik manchmal etwas schwer, aber es ist auch sehr schwer Code zu lesen, der nur aus Namen mit einem Buchstaben besteht.
Wenn du mit Dateien arbeitest solltest du immer den absoluten Pfad verwenden. Ein Pfad ist aber kein einfacher String. Den ein Pfad hat andere Eigenschaften als ein String. Erstellen kannst du den Pfad mit 'pathlib.Path'.
Wenn du eine Datei öffnest, solltest du immer das encoding angeben. Es ist nicht garantiert, das automatisch das richtige genommen wird.
Bei 'range' musst du den 'step' nicht angeben, wenn der 1 sein soll, das ist der default-Wert.
Wieso belegst du 'h_ober' mit -1 und addierst bei der Benutzung 1 dazu? Dann kannst du doch gleich 'h_ober = 0' schreiben?
'h_unter', 'h_ober', 'exponenten_unter' und 'exponenten_ober' sollten Konstanten sein.
An 'plotten' wird 'obergrenze' übergeben, aber nicht benutzt.
Strings formatiert man aktuell eigentlich mit 'f'-Strings.
Wenn die 'obergrenze' 0 ist dann kann sie nicht auch größer 2 sein. Das dritte 'if' in 'intervall_prüfen' sollte ein 'elif' sein. Das heißt, wenn das vorherige True war, dann wird 'elif' gar nicht mehr geprüft. Komischer finde ich aber, das egal ob die Obergrenze 0 oder >2 ist, die Rechnung gleich ist. Zu was dann die Unterscheidung?
Den Sinn hinter 'ausgabe' verstehe ich nicht. Wann setzt man das True? Vielleicht wäre ein sprechenderer Name hier auch hilfreicher.
'B' ist auch so ein Name, aber nicht nur das er nichts aussagt, an der Stelle wollte ich noch sagen, das man Namen klein_mit_unterstrich schreibt. Ausnahmen sind Konstanten GANZ_GROSS und Klassen in PascalCase-Schreibweise.
In 'jacobisymbol' kannst du diesen Ausdruck:
if a == 2:
if n % 8 == 1 or n % 8 == 7:
return 1
else:
return -1
kannst du etwas zusammen rücken:
if a == 2:
return 1 if n % 8 in [1, 7] else -1
Dann kannst du die 'if' an manchen Stellen wieder durch 'elif' ersetzen.
'while' braucht keine Klammern.
In 'bosma' kannst du
if pow(int(D), exp, n) == n - 1:
return [True, D]
return [False, D]
wieder vereinfachen
return [True, D] if pow(int(D), exp, n) == n - 1 else [False, D]
und ein 'elif' einbauen.
Es ist verwirrend wenn eine Funktion zwei Arten von Rückgabewerte hat. Eine Liste oder eine negative Zahl. Normal gibt eine Funktion immer den gleichen Datentyp zurück.
'vektor_anlegen' wird nicht benutzt. Man muss nicht alles an einen Namen binden, wenn man den Namen nur benutzt um ihn danach zum Beispiel zurück zu geben. dann kannst du gleich return laenge * [False] schreiben.
In 'liste_vorbereiten' man will Index so wenig wie möglich benutzen, weil das relativ undurchsichtig ist. Du kannst direkt über den Inhalt der Tuple iterieren:
for x_werte, _, y_roh in vektor:
xwerte.append(x_werte)
y_rohdaten.append(y_roh
In 'liste_vorbereiten' würde ich die Werte nicht als Liste zurück geben, sondern einfach zwei Werte und die dann auch so entgegen nehmen und dabei kannst du dann wieder auf den Index verzichten.
Soviel mal zum Allgemeinen Code. Für mehr Details ist es mir jetzt ehrlich gesagt zu spät und den Zwischenstand von dem hier geschriebenen in Form von Code, reiche ich morgen nach 
Grüße
Dennis