» also ich weiß, es ist nicht sonderlich schnell, aber dafür seeeeeeeehr einfach aufgebaut
» es läuft mindestens ab Delphi 7 (drunter hab ich nicht getestet)
und auch für Delphi 2009 ist es geeignet
» man kann die Verwendung der Unit SysUtils abschalten (incl. der Unit Math, da diese die SysUtils verwendet, aber außer Max wird daraus eh nix verwendet)
» Zahlen mit theoretisch über 1 Milliarde Dezimalstellen sind möglich
» die Funktionen sind mit deutschsprachigen Namen versehn
» es steht unter MPL + (L)GPL
» Versionen: StringMatheLib.pas » Demo 1 » alle Funktionen in einer Klasse verpackt
StringMatheRec.pas » Demo 2 » in einem Record ("MatheString") verpackt und mit Operatoren versehen (ab D2006/TDE)
StringMatheVar.pas » Demo 4 » in einem Variant/"MatheVariant" verpackt und mit Operatoren versehen
StringMatheFloatRec.pas » Demo 3 » wie "MatheString" in einem Record ("MatheStringF") als Festkommazahl
StringMatheParser.pas » Demo 5 » ein kliner Mathe-Parser
// Normalisieren alle ungültigen und zusätzlichen Zeichen entfernen // Formatieren - // // Vergleich - // Vergleich - // istPositiv - // istNegativ - // istGerade - // istUngerade - // gibVorzeichen - // Dezimalstellen - // // Summe r = a + b // Differenz r = a - b // Plus1 a = a + 1 oder inc(a) // Minus1 a = a - 1 oder dec(a) // Negieren a = -a // Absolut if a < 0 then r = -a else r = a // // Produkt r = a * b // Quotient r = a div b // Modulo r = a mod b // QuotientModulo r = a div b und m = a mod b // // Quadrat r = a * a oder r = a ^ 2 // Quadratwurzel r = a ^ 1/2 // Quadratwurzel r = a ^ 1/2 und m = a - (a ^ 1/2) // Potenz r = a ^ b // Potenz10 r = 10 ^ b // // Quotient2 r = a div 2 // Produkt10 r = a * 10^b // Quotient10 r = a div 10^b // Modulo10 r = a mod 10^b // QuotientModulo10 r = a div 10^b und m = a mod 10^b // // SummeModulo r = (a + b) mod m // DifferenzModulo r = (a - b) mod m // ProduktModulo r = (a * b) mod m // PotenzModulo r = (a ^ b) mod m // // Zufall r = Random(von, bis)
Type MatheString = Type AnsiString;
TVergleich = (vUngleich, vKleiner, vKleinerGleich, vGleich, vGroesserGleich, vGroesser);
TMathe = Class Property ImmerNormalisieren: Boolean Read _ImmerNormalisieren Write _ImmerNormalisieren;
Function Normalisieren (a: String): String; Function Formatieren (a: String; TausenderPunkte, ImmerMitVorzeichen: Boolean; Mindestlaenge: Integer = 0): String;
Function Vergleich (a, b: String): TValueRelationship; Overload; Function Vergleich (a, b: String; Art: TVergleich): Boolean; Overload; Function istPositiv (a: String): Boolean; Function istNegativ (a: String): Boolean; Function istGerade (a: String): Boolean; Function istUngerade (a: String): Boolean; Function gibVorzeichen (a: String): Char; Function Dezimalstellen (a: String): Integer;
Function Produkt (a, b: String): String; Function Quotient (a, b: String): String; Function Modulo (a, b: String): String; Procedure QuotientModulo (a, b: String; Var Result, Rest: String);
Function Quadrat (a: String): String; Function Quadratwurzel (a: String): String; Procedure Quadratwurzel (a: String; Var Result, Rest: String); Function Potenz (a, b: String): String; Function Potenz10 ( b: String): String; Function Potenz10 ( b: Integer): String;
Function Quotient2 (a: String): String; Function Produkt10 (a, b: String): String; Function Produkt10 (a: String; b: Integer): String; Function Quotient10 (a, b: String): String; Function Quotient10 (a: String; b: Integer): String; Function Modulo10 (a, b: String): String; Function Modulo10 (a: String; b: Integer): String; Procedure QuotientModulo10(a, b: String; Var Result, Rest: String); Procedure QuotientModulo10(a: String; b: Integer; Var Result, Rest: String);
Function SummeModulo (a, b, m: String): String; Function DifferenzModulo (a, b, m: String): String; Function ProduktModulo (a, b, m: String): String; Function PotenzModulo (a, b, m: String): String;
Function zuInteger (a: String): LongInt; Function vonInteger (a: LongInt): String; Function zuCardinal (a: String): LongWord; Function vonCardinal (a: LongWord): String; Function zuInteger64 (a: String): Int64; Function vonInteger64 (a: Int64): String;
Function Produkt_langsam (a, b: String): String; Procedure QuotientModulo_langsam(a, b: String; Var Result, Rest: String); Function Potenz_langsam (a, b: String): String; End;
» wer die Parameter a und b vor Funktionsaufruf selber normalisiert (also z.B. mindestens einmal nach Eingabe der Werte), der kann .ImmerNormalisieren auf False setzen und es wird dann nicht ständig, beim Starten von Funktionen, durchgeführt ... es wird so also einen Hauch flotter.
Einen Tipp noch zum Schluß: versucht besser nicht eine "größere" Potenz zu berechnen!
(B also nicht zu groß wählen)
[s]Function TMathe.Potenz(a, b: MatheString): MatheString;
Begin
Result := Potenz_langsam(a, b);
End;[/s]
[edit2] wurde geändert
ChangeLog
[edit]
eine Auto-Refresh-CheckBox in den [berechnen]-Button gelegt
[16.06.2009 v1.0]
mit neuer Lizenz versehen (siehe oben)
[30.06.2009 11°° v1.1]
- einige Optimierungen
- Produkt10, Quotient10, Modulo10 und Co. hinzugefügt
- und der MatheParser kam auch dazu[
[30.06.2009 12°° v1.1]
- der Reinfolgefehler aus Beitrag #55 (Potenzen ala x^y^z) wurde behoben
[30.06.2009 12°° v1.1]
- der Reinfolgefehler aus Beitrag #55 (Potenzen ala x^y^z) wurde behoben
[30.06.2009 14°° v1.1]
- weitere Fehler behoben ... siehe #57+#58
- der Fehler bei den Klammern ist hoffentlich behoben #60
[30.06.2009 15:40 v1.1]
- Fehler im Parser #61
[30.06.2009 16:30 v1.2]
- der Mathe-Parser-Demo um einige Features erweitert (wie den Zwischenspeicher)
- Verwaltung der Konstanten, Funktionen und Operatoren erstellt (im Mathe-Parser)
[01.07.2009 00:30 v1.3]
- ein bissl aufgeräumt
- TMathe.Quadratwurzel, TMathe.PotenzModulo und abhängiges stark beschleunigt
- TMathe.Quotient2 eingeführt r := a div 2 (Grund für vorherigen Punkt)
- Demo6 erstellt = "Fließkomma"-Parser (alles mit # rechnet noch mit "falscher" Nachkommabehandlung)
[01.07.2009 10°° v1.3]
- Anfänge eines UnitTests eingefügt
- XPMan wieder entfernt (#67)
- Fehler behoben (#67 inkompatible Typen)
- TMathe.Produkt nach xZise #67 geändert
[01.07.2009 14²° v1.4]
- einige Dateien von UTF-8 nach Ansi konvertiert
- wegen #72 Version erhöht und alles neu kompiliert bzw. hochgeladen
- weitere Konstanten in die Parser eingefügt
[01.07.2009 14³° v1.4]
- Fehler bei internen Verwaltungsoperatoren behoben ... z.B. Komma wurde nicht erkannt
[01.07.2009 19°° v1.4]
- Verzögerungsfehler in Division entfernt, welcher die Rechenoptimierung abschaltete (#76)
- Vergleichsfunktion optimiert (#76)
- Potenz10, Produkt10 und Quotient10 in StringMatheParserFloat.pas berichtig und freigegeben (Nachkommastellenproblem #76)
[01.07.2009 20°° v1.5]
- Rechenfehler aus #67 behoben
[03.07.2009 12°° v1.5]
- Dezimalstellenfunktion mit Fehlerprüfung versehen und die Anzeiger der Stellen in den Demos etwas umgestellt (siehe #79..#81)
[03.07.2009 21³° v1.6]
- .Normalisieren und .Formatieren überarbeitet (#84)
- etwas aufgeräumt und die "InFile"-Hilfe erweitert
- doch wieder auf 7zip umgestiegen (ist 60% kleiner)
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
W := '0'; // #$0034 If W in ['0'..'9'] Then ShowMessage('a');
W := #$1034; If W in ['0'..'9'] Then ShowMessage('b');
wo einfach nur der obere Teil abgeschnitten wurde und am Ende auch 'b' angezeigt wurde
na gut, aber die Warnmeldung gefällt mir dann dennoch nicht,
vorallem wo Delphi schon seit vielen Jahren auch mit mehr, als einem Byte klarkommt, solange es die Möglichkeit zum Kürzen/Optimieren hat ... Integer und Word sind ja locker möglich, nur WideChar (=Word) nicht
nja, ...
- MatheString jetzt als String
- der Operatoren-Record in MatheString umbenannt
- und gegen die nervigen Compiler-Hinweise hab ich auch was garnicht soooooo unschönes gefunden
- einige fehlende Dinge noch in den Record durchgeschleift
- alle Dateien im Post #1 geupdatet
Bevor Du die Sache weiter ausbaust, hier ein paar Bugs/Features :)
- QuotientModulo('7','-3') liefert Quotient -2, Rest -1. Richtig ist Quotient -2, Rest +1. Es ist zwar immer wieder ein Graus, daß -7 mod 3 = -1 sein soll (und nicht 2), aber das ist wenigstens mit Pascal kompatible.
- Sinnvoll ist mM auch die Verwendung von Fehler "reRangeError" bei Wurzeln, Potenzen etc; denn "reInvalidOp" liefert "Invalid floating point operation" und das ist bei einer Ganzzahlbibliothek doch etwas unerwartet.
mir verschliesst sich momentan der Sinn des Ganzen.
Für was benutzt man diese Unit. Rechnen kann ich ja auch so oder?
jetzt versuche es mal mit "größeren" Zahlen
Die Funktionen, welche dir Delphi/der PC bietet, arbeiten maximal mit 20 Dezimalstellen ... wenn die Zahl mehr Dezimalstellen hat, dann sind die Nachfolgenden Aufgrund der internen Art der Speicherung undefiniert, also bei Extended und Co.
Int64 hat maximal 19 Dezimalstellen.
Hier sind weit mehr Dezimalstellen möglich.
Ansonsten hat es, so wie diese Lib aufgebaut ist, mehr einen spielerischen Lernfaktor.
(hier ist zwar viel möglich, aber nicht unbedingt schnell ... für schnelle Berechnungen gibt es weitaus Beseres, aber es Rechnet "jetzt" immer genau und das bis zu letzten Dezimalstelle und der Code ist recht einfach und Verständlich ... falls mal wer da gern reinguck und etwas verstehen will)
In ein/zwei Minütchen sind dann auch alle Dateien wieder UpToDate und ohne diesen Fehler bim MOD
(hatte die Vorzeichen einfach nur falsch behandelt)
wenn ich jetzt noch wüsste, wie ich die lib in meine unit einbinde, und die fkt's benutze, dann wäre alles super.
weitere fehler habe ich keine gefunden beim test, aber benutzen würde ich sie schon gerne in meinem project.
- erstmal entscheiden, welche Version man möchte
> mit Objekt (diese wäre auch Threadsicher, wenn je Thread ein eigenes Objekt genutzt würde)
> als Record/MatheString
Noch ein schwerer Bug in PotenzModulo sollte es heißen While Vergleich(b,'0',vGroesser) doBegin
statt "istPositiv(b)", denn sonst kommt man in Endlosschleifen zb für 2^11 mod 13.
weitere fehler habe ich keine gefunden beim test, aber benutzen würde ich sie schon gerne in meinem project.thx
Du willst doch RSA implementieren. Da ist die wichtigste Operation PotenzModulo. Wenn Du den von mir gefundenen Bug beseitigt hast, solltest Du unbedingt mal ausprobieren wie lange Dein Projekt rechnet. Bei mir im Sekundenbereich für 64 Bit. Also wird wohl alles über 128 Bit illusorisch (wahrscheinlich schon viel früher). Und 512-1024 Bits sollten es schon sein. Es sei denn, Du willst nur das Prinzip versehen, aber dafür hätten ach int64 gereicht.