Das Material auf dieser Seite ist entstanden wegen meines Interesses an der Zahlentheorie, ein Forschungsgebiet woher vielen klassischen Algorithmen stammen, die man ohne Verzögerung implementieren möge um ihre Wirkungsmagie zu beobachten. Aber leider, sobald die Sachen fesselnd werden, gelangt man an die Grenzen die das Gerät auferlegt:
‘[..] Die Anzahl von Symbole welche der Rechner in einem Moment beachten kann, ist beschrankt. Wenn er wünscht Mehre zu beachten, muß er aufeinander folgenden Operationen verwenden.’ Alan Turing, Auf berechenbaren Zahlen [..], 1936.
Deshalb brauchte ich eine kleine Programmbibliothek um die Grundrechenarten nach ‘aufeinander folgenden Operationen’ umzuformulieren. Anstatt einen existierenden Bibliothek zu benützen, bevorzugte ich eine Minimum-Menge bündigen Operationen, die von den untenstehenden Langzahl-Modulen aufgerufen werden, selbst zu implementierten.
Das Projekt wuchs unter eigenem Antrieb und einigen ziemlich nützlichen Funktionen werden hinzugefügt. Es gibt Versionen für QuickBasic, FreeBasic, XBasic und Visual Basic. Bitte besuchen Sie die Download-Seite für Einzelheiten.
' ************************************************************************* 'Thema: Einfügeeinheit-Datei für eine Langzahl BASIC-Programmbibliothek. 'Autor: Sjoerd.J.Schaper 'Datum: 02-02-2004 'Code : QuickBasic, PDS, VBdos ' ' **************************************************************************** ' Initialisierung und Zuweisung ' **************************************************************************** 'Die LargeInt-Klasse wird mit einem 'LargeInit(Größe%, Name$)' Aufruf am 'Modul-Niveau initialisiert. Für alle Langzahlen die Sie verwenden wollen, 'sollen Sie (konstante) Indizes angeben ('CONST p = 0, q = 1, ..'), so daß 'jede Zahl mit einem eindeutigen Spaltenzeiger verbunden wird. Diese Zeigern 'werden dann den Prozeduren übergeben. Sie sollen keinen Funktions-Aufrufe 'mit gleichen Zeigern machen ('Squ p, p'), und sich hüten für Doppelver- 'weisungen, weil diese Programmabstürze verursachen. ' 'In nachfolgenden Prototypen, 'sind die Buchstaben p, q, r, d, m 16-Bit (Pseudo)Zeigern zur Langzahlen; 'die Variablen a, k, sw 16-Bit Ganzzahlen, c ist eine 32-Bit Ganzzahl; 'g ist eine Zahlzeichenkette, f und h sind irgendwelche Zeichenketten. 'Die t-Nummern zwischen geschwungen Klammern bedeuten die Reihe der 'Zwischenregister die von der Subroutine verwendet werden, und nicht als 'Argumente übergeben werden können. ' DEFINT A-B, D-Z: DEFLNG C DECLARE FUNCTION LargeInit% (k, f AS STRING) 'Initialisiert die Zahlen-Arrays, öffnet die Primzahltabelle und Logdatei. 'Auf zu rufen mit k = Anzahl der Largeint-Zahlen in ihrem Programm '(k <= 432 in der $STATIC-Version) und String f = Programm-Namen. 'Falls f = "" wird keine Logdatei geöffnet. 'Rückgabewert ist die maximale Langzahllänge gemessen in Array-Elementen '(='Worte'). Die Dezimalzahl-Länge ist annäherend 4.51 * Langzahllänge. 'Falls ein Überlauf stattfindet, so muß die Maß Asize des Zahlen-Arrays 'im Largeint.bas erhöht, und der Bibliothek neu kompiliert werden. ' DECLARE SUB Letf (p, c) 'Weist Langzahl p den vorzeichenbehafteten Doppelwortwert c zu. ' DECLARE SUB Readst (p, g AS STRING) 'Weist Langzahl p die (hexa)dezimale Zahlzeichenkette g zu. 'Die Zeichenkette wird nicht auf Nichtziffer-Charaktere überprüft, 'mit Präfix &H wird der Zeichenkette hexadezimal interpretiert. {t1..t2} ' DECLARE SUB Rndf (p, k) 'Weist Langzahl p eine positive Zufallszahl der Bitlänge k zu. ' DECLARE FUNCTION LibErr% () 'Gibt den Laufzeitfehler-Kode zurück und löscht ihn dann. ' DECLARE SUB Term () 'Schließen der Primzahltabelle und Logdatei. ' ' **************************************************************************** ' Funktionen zur Konvertierung ' **************************************************************************** DECLARE FUNCTION Logf# (p) 'Natürlicher Logarithmus von |Langzahl p| in doppelte Genauigkeit. ' DECLARE FUNCTION Bufl% (p) 'Gibt die maximale Zahlzeichenlänge von dezimal(p) zurück, 'auf zu rufen bevor CnvSt. ' DECLARE SUB CnvSt (g AS STRING, p) 'Konvertiert Langzahl p in eine dezimale Zahlzeichenkette. 'Legen Sie erst eine Zeichenkettenpuffer g = STRING$(Bufl(p), "0") an, 'und übergeben Sie diesen am CnvSt. {t2} ' DECLARE SUB RatCnv (g AS STRING, p, q, a) 'Konvertiert Zahlenverhältnis p / q in eine k-lange Zahlzeichenkette 'von Ziffern der basis a, 2 <= a <= 17. Übergeben Sie Zeichenkettenpuffer 'g = STRING$(k, "0"), 9 < k < 32768. {t0..t3} ' ' **************************************************************************** ' Datenausgabe ' **************************************************************************** DECLARE SUB Printn (p, f AS STRING, h AS STRING, sw) 'Druckt Langzahl p mit Vorspann f und Schwanzende h zum Bildschirm und 'der Logdatei. Mit switch = 1 wird einem CrLf, sw = 2 auch der Länge von p 'angeheftet. {t2} ' DECLARE SUB Printr (p, q, f AS STRING, k, sw) 'Druckt die Dezimaldarstellung von Zahlverhältnis p / q ab mit der länge k. 'Setzen Sie switch = 1 um ein CrLf an zu heften. {t0..t3} ' DECLARE SUB Prints (f AS STRING, sw) 'Druckt die Zeichenkette f ab, 'setzen Sie switch = 1 um ein CrLf an zu heften, switch = 2 für Zweier. ' DECLARE SUB Work (f AS STRING) 'Gibt das Arbeits-Dateiverzeichnis im ENVIRON$("LARGEINT") zurück. 'Der Puffer f soll genügend groß sein um den Pfad zu behalten. ' ' **************************************************************************** ' grundlegende Rechenfunktionen ' **************************************************************************** DECLARE SUB Subt (p, q) 'Subtrahiert q von p, das Ergebnis steht in p. ' DECLARE SUB Add (p, q) 'Addiert p und q, das Ergebnis steht in p. ' DECLARE SUB Inc (p, a) 'Erhöht Langzahl p mit dem vorzeichenbehafteten Einwortwert a. ' DECLARE SUB Divd (p, d, q) 'Dividiert p und d, der Quotient steht in q, der Rest in p. {t2} ' DECLARE FUNCTION Divint% (p, a) 'Dividiert Langzahl p mit |Einwortwert a|, 'gibt der |Rest| zurück und setzt p zum Quotient. ' DECLARE SUB Ldiv (p, d) 'Setzt p zum Quotient p / d. {t1..t2} ' DECLARE SUB Mult (p, q, r) 'Multipliziert p und q, das Ergebnis steht in r. ' DECLARE SUB Lmul (p, q) 'Setzt p zum Produkt p * q. {t2} ' DECLARE SUB Squ (p, q) 'Gibt das Quadrat von p in q zurück. ' DECLARE SUB Powr (p, c) 'Potenziert Basis p mit |Hochzahl c|, und setzt p zur Potenz. {t0..t2} ' DECLARE SUB Chs (p) 'Änderung des Vorzeichens von Langzahl p. ' DECLARE FUNCTION Absf% (p) 'Löscht das Vorzeichenbit von Langzahl p, gibt den jetzigen Wert zurück. ' ' **************************************************************************** ' Kopieren und Vergleich ' **************************************************************************** DECLARE SUB Dup (p, q) 'Kopiert Langzahl p zu q. ' DECLARE SUB Swp (p, q) 'Täuscht Langzahlen p und q. ' DECLARE FUNCTION Cmp% (p, q) 'Vergleicht p und q: 'das Resultat ist -1 falls p < q, 0 falls p = q, und 1 falls p > q. ' DECLARE FUNCTION Isf% (p, a) 'Boolesch: überprüft ob Langzahl p gleich den Einwortwert a ist. ' DECLARE FUNCTION Ismin1% (p, m) 'Boolesch: überprüft ob p = m - 1 ' ' **************************************************************************** ' Bit-Verarbeitung ' **************************************************************************** DECLARE SUB Boolf (p, q, k) 'Bitweise boolesche Funktionen setzen p zu q Op(k) p, mit Op(1) = AND, 'Op(2) = XOR, Op(3) = OR. Falls k = 0 wird p zu NOT p gesetzt und q ignoriert. 'Jeweils bleibt das Vorzeichen von p unverändert. ' DECLARE SUB Lsft (p, k) 'Langzahl p wird um k Bits nach links verschoben, 'k < 0 schiebt |k| ganze Worte. ' DECLARE SUB Rsft (p, k) 'Langzahl p wird um k Bits nach rechts verschoben, 'k < 0 schiebt |k| ganze Worte. ' DECLARE FUNCTION Odd% (p) 'Entfernt abschließende Null-Bits aus der Langzahl p, 'Rückgabewert ist die (rechts) Schiebezahl. ' DECLARE FUNCTION Bitl% (p) 'Gibt die Bitlänge von Langzahl p zurück. ' ' **************************************************************************** ' Modular-Arithmetik ' **************************************************************************** DECLARE SUB Moddiv (p, m) 'Gibt den positiven Rest p modulo m. {t1..t2} ' DECLARE SUB Modbal (p, m) 'Gibt den ausgeglichenen Rest p modulo m: |p| <= m / 2. {t1..t2} ' DECLARE FUNCTION Mp2% (p, a) 'Gibt Langzahl p modulo a zurück, mit a einem Einwortwert Potenz-von-Zwei. ' DECLARE SUB Modmlt (p, q, m) 'Multipliziert p und q, reduziert dann modulo m. {t1..t2} ' DECLARE SUB Modsqu (p, m) 'Quadriert p, reduziert dann modulo m. {t1..t2} ' DECLARE SUB Modpwr (p, q, m) 'Modulares Potenzieren: Basis p, Hochzahl q, Modulus m. 'Das Ergebnis steht in p. {t0..t2, t3 falls q < 0} ' ' **************************************************************************** ' zahlentheoretische Funktionen ' **************************************************************************** DECLARE SUB Fctl (p, a) 'Berechnet Fakultät a(a-1)···2·1 in Langzahl p. {t1..t2} ' DECLARE SUB Lcm (p, q, d) 'Gibt das kleinste gemeinsame Vielfache (p, q) in d zurück. {t0..t2} ' DECLARE SUB Gcd (p, q, d) 'Gibt den größte gemeinsame Teiler (p, q) in d zurück. {t0..t2} ' DECLARE SUB Euclid (p, q, d) 'Der erweiterte Euklidische Algorithmus setzt 'p zu 1/p (modulo q), q zu q/ggT, und d zum ggT(p, q). {t0..t2} ' DECLARE SUB Bezout (p, q, d) 'Lösung der diophantische Gleichung px + qy = ggT(p, q), 'setzt Langzahl p zu x, q zu y, und d zum ggT(p, q). {t0..t3} ' DECLARE SUB Isqrt (p, q, r) 'Setzt r zur Ganzzahl-Quadratwurzel von p, und q zum Reste 'p - r ^ 2. {t0..t2} ' DECLARE FUNCTION IsSqr% (p, r) 'Boolesch: überprüft ob p ein reines Quadrat ist, und falls wahr, 'setzt r zur Wurzel. {t0..t3} ' DECLARE FUNCTION Kronec% (p, q) 'Gibt das quadratische Restsymbol Kroneckers (p/q) = 0, 1, oder -1. {t0..t3} ' DECLARE FUNCTION IsPPrm% (p, d, k) 'Überprüft die Primalität von p mit dem Miller-Rabin-Test. 'Rückgabewert 1 falls p bestimmt prim ist, -1 wahrscheinlich prim, '0 falls p zusammengesetzt. K ist die Anzahl der Zeugen im Test, 'setze k < 0 um die anfänglichen Probedivisionen zu überspringen. {t0..t3} ' DECLARE FUNCTION Nxtprm& (sw) 'Schleift durch Tabelle PrimFlgs.bin. Initiieren mit sw = 0, danach 'gibt ungeraden(sw) die nächste Primzahl bei jedem folgenden Aufruf. 'Mit sw = 2 der jetzigen Lage ablegen (Push) und Neustarten, 'mit sw =-2 wieder entnehmen (Pop). ' DECLARE FUNCTION PrimCeil& () 'Gibt die obere Begrenzung der Primzahltabelle PrimFlgs.bin zurück. ' DECLARE SUB Triald (q, p, c) 'Probedivision von p bis Schranke c. Primfaktoren und Exponenten werden in 'die Liste {q} gespeichert, der Restfaktor wird in p zurückgegeben. {t0..t3} ' ' **************************************************************************** ' direkter Zugrif ' **************************************************************************** DECLARE SUB EnQ (q, p, a) 'Speichert Langzahl p und |Einwortwert a| in sequentielle Liste {q}. 'Weil {q} negativen Trennzeichen enthält, wird ein einfaches Kommando 'Printn q, ...' Programmabstürz verursachen. Verwenden Sie stattdessen: ' DECLARE FUNCTION ExQ% (p, a, q, k) 'Herausziehen der sukzessiven Zahlen p und |a| aus der Liste {q} mit 'Versetzung k. Initiieren mit k = 0, Wert ist Null wenn am Ende der Liste. ' DECLARE FUNCTION Getl% (p) 'Gibt die Länge der Langzahl p zurück, gemessen in Worten. ' DECLARE FUNCTION Gets% (p) 'Gibt das Vorzeichenbit der Zahl p zurück: -32768 falls p < 0, sonst Null. ' DECLARE FUNCTION Getw% (p, k) 'Gibts Wort k der Langzahl p zurück: eine Ziffer der Basis MB (siehe unten). ' DECLARE SUB Setl (p, a) 'Setzt die Länge der Langzahl p auf a Worte. ' DECLARE SUB Sets (p, a) 'Setzt das Vorzeichenbit von Langzahl p falls a < 0, sonst löscht's. ' DECLARE SUB Setw (p, k, a) 'Setzt Wort Numero k der Langzahl p auf |a| < MB. ' ' **************************************************************************** ' interne Funktionen ' **************************************************************************** DECLARE SUB Printf (f AS STRING, g AS STRING, h AS STRING, sw) 'Die gemeine Druck-Funktion. ' DECLARE SUB Errorh (f AS STRING, sw) 'Zeigt eine Fehlermeldung an. ' DECLARE SUB Lftj (p, k) 'Langzahl p wird links justiert ab Wort Numero k. ' DECLARE FUNCTION Hp2% (p) 'Rückgabewert 2^(höchste gesetzte Bit im äußerst Linken Wort der Langzahl p). ' ' **************************************************************************** ' BASIC Prototypen für Maschinensprache-Unterstützung ' **************************************************************************** DECLARE SUB SftL (c, BYVAL k) 'Long Integer c wird um k (modulo 32) Bits nach links verschoben. ' DECLARE SUB SftR (c, BYVAL k) 'Long Integer c wird um k (modulo 32) Bits nach rechts verschoben. ' DECLARE FUNCTION EstQ% (SEG a, c) 'Bildet ein 45-Bits Teilungszahl-Präfix, teilt durch 30-Bits Präfix 'und gibt einen 15-Bit Probe-Quotienten zurück. ' DECLARE SUB Ffix () 'Repariert den FWAIT Programmfehler ins QB FPU Emulator-Library. ' ' **************************************************************************** ' globale Konstanten ' **************************************************************************** CONST LB = 15, MB = &H8000& ' binär Speicherbase CONST LD = 4, MD = 10000 ' dezimale Zahlzeichenkettebase < MB CONST t0 = -1, t1 = -2 ' Zeigern zu Wechselregistern CONST t2 = -3, t3 = -4 ' ' ****************************************************************************
Mit der Programmbibliothek kommen einigen BASIC-Module betreffend die Zahlentheorie, die als Testumfeld dienen können. Lassen Sie sie laufen mit den Beispiel-Eingabedateien um Korrektheit und Leistung der Bibliothek zu zeigen. Alle Module sind im Englisch verfaßt.
Sehen Sie den Liesmich.txt ein
Spiegel Seite (in English)
Die Ackermannsche Funktion in Basic (English).
Es gibt auch einen Anhang: Arithmetik in endlichen Körper (English).
Buchliste:
Verzicht:
Dieser BASIC-Code für Langzahlen (großen Ganzzahlen, big numbers, grands nombres entiers, grandi numeri interi, números enteros grandes, inteiros grandes, μεγάλοι ακέραιοι αριθμοί, больших целых чисел, الأعداد الصحيحة الكبيرة usw.) wird kostenlos verteilt in der Hoffnung daß es nützlich sein wird, aber ohne Garantie jeder Art, sogar die implizierte Garantie der Marktgängigkeit oder Angemessenheit zu einem bestimmten Zweck. Erlaubnis ist bewilligt für das ändern Ihrer Kopie des Codes oder die Formung einer nicht-kommerziellen Anwendung, die auf ihn basiert, und solche Kopien und änderungen zu verteilen, vorausgesetzt daß der geänderte Inhalt einen Hinweis auf dem Urheber des Quellcodes und Nachrichten angebend trägt, daß er geändert worden ist und von wem.