Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   Mathe mit Strings (die deutsche StringMatheLib ._. ) (https://www.delphipraxis.net/135569-mathe-mit-strings-die-deutsche-stringmathelib-_.html)

himitsu 13. Jun 2009 12:40


Mathe mit Strings (die deutsche StringMatheLib ._. )
 
Liste der Anhänge anzeigen (Anzahl: 4)
Jaaaaaaa, was soll ich sagen ...

» also ich weiß, es ist nicht sonderlich schnell, aber dafür seeeeeeeehr einfach aufgebaut :angel2:

» es läuft mindestens ab Delphi 7 (drunter hab ich nicht getestet)
und auch für Delphi 2009 ist es geeignet :mrgreen:

» 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 :shock:

» 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


» was es derzeit kann ... siehe hier:
Delphi-Quellcode:
// 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 Summe          (a, b: String): String;
  Function Differenz      (a, b: String): String;
  Procedure Plus1       (Var a:   String);
  Procedure Minus1      (Var a:   String);
  Procedure Negieren   (Var a:   String);
  Function Absolut        (a:   String): String;

  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. :nerd:



Einen Tipp noch zum Schluß: versucht besser nicht eine "größere" Potenz zu berechnen!
(B also nicht zu groß wählen)

Code:
[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 Bei Google suchen7zip umgestiegen (ist 60% kleiner)

himitsu 14. Jun 2009 15:41

Re: die deutsche StringMatheLib ._.
 
nur 'ne winzig kleine Änderung

- Potenz wurde richtig eingebaut

- über den Edits wird in Klammern die Anzahl der Dezimalstellen eingeblendet

- so, daß war's auch schon

- ach ja, bei den Potenzen wird eine Warnung angezeigt, ob man wirklich will, wenn der Exponent viel zu groß ist und es seeeeeeeehr lange dauern würde


z.B. 1234567890123456789^50 wird in nur 0,8 Sekunden berechnet
und ergibt ein Ergebnis mit 905 Dezimalstellen

und 1234567890123456789 * 987654 braucht nur 0,04 Millisekunden

qwertz543221 14. Jun 2009 18:22

Re: die deutsche StringMatheLib ._.
 
nöö üüüberhaupt nicht schnell;)(achtung: ironie!!)

das ist richtig toll, was du da produziert hast. so gut hätte ich das doch nie hinbekommen.

genau das was ich gebraucht habe

THX

himitsu 14. Jun 2009 18:56

Re: die deutsche StringMatheLib ._.
 
Also gegen mein altes Hier im Forum suchenTBigInt sollte dieses um Längen langsamer arbeiten (auch wenn ich noch keinen Vergleich der beiden Typen angestellt hab) und vorallem bei den "höheren" Funktionen kommt selbst TBigInt nicht gegen sowas Hochoptimiertes wie das DEC an.

himitsu 14. Jun 2009 23:17

Re: die deutsche StringMatheLib ._.
 
kleines Update mit Operatoren ... siehe Demo2 :angel2:

GPRSNerd 15. Jun 2009 09:52

Re: die deutsche StringMatheLib ._.
 
Hi himitsu,

Hut ab! Klasse Unit, die ich auch sofort für ein altes Zahlenkonvertier-Problem in einem meiner Programme einsetzen kann.

Ich habe mich nur gefragt, warum du Mathestring auf AnsiString typecastes und in ein paar Funktionen explizit AnsiStrings und AnsiChars benutzt und nicht generell String und Char?
Ich habe das mal umgestellt und soweit ich das übersehen kann und getestet habe, läufts dann auch mit Unicode-Strings unter D2009.

Interesse an den geänderten Sourcen?

Gruß,
Stefan

himitsu 15. Jun 2009 10:10

Re: die deutsche StringMatheLib ._.
 
Also die neue Operator-Unit hatte ich auf MatheRString ausgelegt und nur die externen Zuweisungen als AnsiString, WideString und Int64 vorgesehn ... beim anderen hatte ich in Bezug auf Delphi2009 es MatheString genannt.

Wenn ich da String und Char nehme, ist erstmal der Speicherverbrauch doppelt so hoch, was aber erstmal egal ist.
Aber schlimmer ist, daß man bei String/UnicodeString in D2009 kein IN [...] mehr verwenden kann.

Drum wurde alles "explizit" als AnsiString/MatheString definiert.


In der StringMatheLib.pas sollte aber, bist auf das Trim für D2009 (da es dort blöder Weise keine überladene Ansi-Verion gibt) alles als MatheString definiert.


Und das "MatheString" hatte ich so genommen, damit es besser auffällt und man nicht so ausversehn mal mit AnsiString/WideString/UnicodeString/String in Konflikt kommt und man nimmer weiß, was man nehmen soll,
außerdem paßt der Name so besser zur Record-Version :angel:

GPRSNerd 15. Jun 2009 10:17

Re: die deutsche StringMatheLib ._.
 
OK, danke für die Erklärungen.

Anbei ein kleiner Code-Schnipsel als Ersatz für CharInSet unter Delphi<=2007:

Delphi-Quellcode:
{$IFNDEF COMPILER12_UP}
function CharInSet(C: AnsiChar; const CharSet: TSysCharSet): Boolean;
begin
  Result := C in CharSet;
end;
{$ENDIF !COMPILER12_UP}
Edit: Der Define COMPILER12_UP kommt aus der Jedi.inc, kann aber auch direkt ersetzt werden.

himitsu 15. Jun 2009 10:34

Re: die deutsche StringMatheLib ._.
 
klappt nicht ganz ... die "umständliche" Variante ist eher:
Delphi-Quellcode:
function CharInSet(C: Char; const CharSet: TSysCharSet): Boolean;
begin
  Result := (C <= #$00FF) and (AnsiChar(Word(C)) in CharSet);
end;
Und für diese Funktion 32 Byte für ein TSysCharSet ständig hin- und herzukopieren? :gruebel:
(hätt das dann eher direkt in die ganzen Abfragen eingebaut, da so Delphi dann optimieren kann)

Das wollte ich dem Code nicht antun, drum bin ich beim ANSI geblieben.
Aber mal sehn, vielleich finde ich ja noch was "Schönes".

GPRSNerd 15. Jun 2009 10:45

Re: die deutsche StringMatheLib ._.
 
Eh... Die Funktion ist doch für alle Delphis 2007 und älter. Da ist ein Char=AnsiChar = immer <=$FF oder?

himitsu 15. Jun 2009 11:45

Re: die deutsche StringMatheLib ._.
 
ahhhh, dann haben die das wohl doch schon ausgebessert :shock:

hatte mal das Problem hiermit,
Delphi-Quellcode:
Var W: WideChar;

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 :wall:

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 :angel2:
- einige fehlende Dinge noch in den Record durchgeschleift
- alle Dateien im Post #1 geupdatet

gammatester 15. Jun 2009 13:30

Re: die deutsche StringMatheLib ._.
 
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.

R2009 15. Jun 2009 13:51

Re: die deutsche StringMatheLib ._.
 
Hm äähm,

mir verschliesst sich momentan der Sinn des Ganzen.
Für was benutzt man diese Unit. Rechnen kann ich ja auch so oder?

Für die Addition:
c:=floattostr(strtofloat(a)+strtofloat(b))
Warum dann der immense Aufwand?

Das ist doch alles, oder entgeht mir da was?

Viele Grüsse!

alzaimar 15. Jun 2009 14:17

Re: die deutsche StringMatheLib ._.
 
Zitat:

Zitat von R2009
mir verschliesst sich momentan der Sinn des Ganzen.

Spass.

Zitat:

Zitat von R2009
Rechnen kann ich ja auch so oder? Für die Addition:
c:=floattostr(strtofloat(a)+strtofloat(b))
Warum dann der immense Aufwand?

Deswegen
Delphi-Quellcode:
a := '1'+ StringOfChar('0',10000000000);
b := '2'+ StringOfChar('1',maxint);
c:=floattostr(strtofloat(a)+strtofloat(b))
:zwinker: Die Unit ist zum genauen Rechnen mit großen (sehr großen) Zahlen gedacht.

Zitat:

Zitat von R2009
Das ist doch alles, oder entgeht mir da was?

Jep.

qwertz543221 15. Jun 2009 14:23

Re: die deutsche StringMatheLib ._.
 
ja schon, aber hier geht es um großere ganzzahlen als int64, die dargestellt werden sollen

deshalb kann man die normalen, in delphi integrierten, fkt's nicht benutzen

himitsu 15. Jun 2009 14:43

Re: die deutsche StringMatheLib ._.
 
Zitat:

Zitat von R2009
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 :oops:
(hatte die Vorzeichen einfach nur falsch behandelt)

qwertz543221 15. Jun 2009 14:50

Re: die deutsche StringMatheLib ._.
 
ach ja, himitsu.

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.

nochmal danke für die mühe

thx

himitsu 15. Jun 2009 15:11

Re: die deutsche StringMatheLib ._.
 
Ja eigentlich recht einfach

- 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

Delphi-Quellcode:
Uses StringMatheLib;      // Unit eintragen

Var Mathe: TMathe;        // an passender Stelle das Objekt definieren
  a, b, c: String;        // Variablen definieren

Mathe := TMathe.Create;   // dieses Objekt erstellen

a := '123';               // nun dieses benutzen
c := Mathe.Summe(a, b);   // ...
c := Mathe.Potenz(a, b);  // 
Edit1.Text := c;
Edit2.Text := Mathe.Format(c, True, False);
...

Mathe.Free;               // und am Ende noch aufräumen
Delphi-Quellcode:
Uses StringMatheRec;     // Unit eintragen

Var a, b, c: MatheString; // Variablen definieren

a := '123';               // nun dieses benutzen
c := a * b;               // ...
c := Power(a, b);         //
Edit1.Text := c;
Edit2.Text := c.Format(True, False);
...

// hier wird das nötige TMathe-Objekt intern automatisch erstellt und freigegeben

gammatester 15. Jun 2009 15:13

Re: die deutsche StringMatheLib ._.
 
Noch ein schwerer Bug in PotenzModulo sollte es heißen
Delphi-Quellcode:
While Vergleich(b,'0',vGroesser) do Begin
statt "istPositiv(b)", denn sonst kommt man in Endlosschleifen zb für 2^11 mod 13.

gammatester 15. Jun 2009 15:20

Re: die deutsche StringMatheLib ._.
 
Zitat:

Zitat von qwertz543221
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.

himitsu 15. Jun 2009 15:27

Re: die deutsche StringMatheLib ._.
 
Zitat:

Zitat von gammatester
Noch ein schwerer Bug in PotenzModulo ...

ups, das hatte ich mal so und hatte es dann wohl "zeroptimiert" :roll:

Aber hier hat sich schonmal ein Vorteil der "Einfachheit" gezeigt ... nicht viel unverständlicher Code, dann noch fast vollkommen unkommentiert und dennoch ist der Fehler schnell gefunden :)
(ich möcht mal nicht wissen, wieviele Zeilen Code Hagens DEC allein in solch einer Funktion drinnen hat)

Nja, auf die Geschwindigkeit hatte ich ja schon hingewiesen ... probiert einfach mal eine Potenz, mit den voreingetragenen Standardwerten :angel2:

qwertz543221 15. Jun 2009 15:29

Re: die deutsche StringMatheLib ._.
 
sry ich finde die angebene zeile nicht

kannst du mir mal die zeilennummer geben

himitsu 15. Jun 2009 15:30

Re: die deutsche StringMatheLib ._.
 
Zeile 520 in StringMatheLib.pas ... und die Dateien im Post #1 sind auch schon korrigiert :mrgreen:

qwertz543221 15. Jun 2009 15:47

Re: die deutsche StringMatheLib ._.
 
wie stelle ich folgendes dar

Delphi-Quellcode:
if (x>y)
  then ...

himitsu 15. Jun 2009 18:12

Re: die deutsche StringMatheLib ._.
 
Delphi-Quellcode:
// über das TMathe-Objekt

If Mathe.Vergleich(x, y) > 0 Then ...
// die Vergleiche des Funktions-Ergebnisses gegen 0 verhalten sich genauso, wie x gegen y
// ..) > 0       x > y
// ..) < 0       x < y
// ..) = 0       x = y
// ..) >= 0      x >= y
// ...

If Mathe.Vergleich(x, y, vGroesser) Then ...

// über die Operatoren aus StringMatheRec.pas

If x > y Then ...

PS: falls es richtig rechnet, gibt es nun auch einen Festkommatypen (siehe Demo 3)

qwertz543221 15. Jun 2009 20:32

Re: die deutsche StringMatheLib ._.
 
hallo, danke - ich kann das jetzt gut einbauen.

hast du vlt auch eine random funktion für deine stringzahlen? - oder eine idee, die ich mal - ausnahmsweise - selbst mache;)

mkinzler 15. Jun 2009 21:56

Re: die deutsche StringMatheLib ._.
 
Zitat:

hast du vlt auch eine random funktion für deine stringzahlen? - oder eine idee, die ich mal - ausnahmsweise - selbst mache;)
Das würde zumindest dem Gedanken von OpenSource entsprechen :zwinker:

R2009 16. Jun 2009 05:14

Re: die deutsche StringMatheLib ._.
 
Hi,

Aus deinem Titel und aus den Beiträgen hatte ich den Eindruck du wolltest ausschliesslich mit Strings rechnen!
Dass es hier um sehr grosse Zahlen geht kann man nur ganz am Rande im ersten Beitrag erahnen.

Viel grüsse

toms 16. Jun 2009 05:37

Re: die deutsche StringMatheLib ._.
 
Die Unit läuft fast unter Delphi 5.

Folgende Punkte müssten noch bereinigt werden:

1. unit types entfernen

2. TValueRelationship und Konstanten von unit types deklarieren

Delphi-Quellcode:
type
  TValueRelationship = -1..1;
const
 (** Equals for extended comparisons. *)
  EqualsValue = 0;
  (** Less than for extended comparisons. *)
  LessThanValue = Low(TValueRelationship);
  (** Greater than for extended comparisons. *)
  GreaterThanValue = High(TValueRelationship);

3. "$IF not" ist unter D5 eine ungültige Compiler Directive.

{$IF not Declared(Trim)} -> [Error] StringMatheLib.pas(107): Invalid compiler directive: 'IF'
{$IF not Declared(Max)} -> [Error] StringMatheLib.pas(123): Invalid compiler directive: 'IF'


4. Delphi 5 kennt System.Error nicht

himitsu 16. Jun 2009 06:41

Re: die deutsche StringMatheLib ._.
 
1-3 sind kein Problem

4: wie hieß das denn früher, bzw. gibt es da zumindestens System.RunError?

Corpsman 16. Jun 2009 07:00

Re: Mathe mit Strings (die deutsche StringMatheLib ._. )
 
Oh man, ich hab grad auch versucht das teil nach D5 zu portieren und hatte die Selben Fehler wie in Post 29 hätt ich doch zuerst gelesen, naja ...
ich habe
Delphi-Quellcode:

  If istNegativ(b) Then System.Error(reInvalidOp);
zu
Delphi-Quellcode:

If istNegativ(b) Then raise Exception.create('reInvalidOp');
gemacht.

Das RunError gibts zwar, aber die ganzen Konstanten reInvalidOp .. müste man dann auch noch setzen.

himitsu 16. Jun 2009 07:24

Re: Mathe mit Strings (die deutsche StringMatheLib ._. )
 
Zitat:

Zitat von Corpsman
Das RunError gibts zwar, aber die ganzen Konstanten reInvalidOp .. müste man dann auch noch setzen.

Da muß ich nur mal in der Umrechnungstabelle nachsehn ... die Codes haben da nur andere Werte (und Byte statt SET)

Delphi-Quellcode:
Function Zufallszahl(Mathe: TMathe; Const von, bis: String): String;
  Var d: String;
    s, i: Integer;

  Begin
    If Mathe.Vergleich(von, bis) > 0 Then System.Error(reRangeError);
    d := Mathe.Differenz(bis, von);
    Mathe.Plus1(d);
    SetLength(Result, Length(d) * 2 + 33);
    s := RandSeed;
    For i := Length(Result) downto 1 do Result[i] := Char(Random(10) + Ord('0'));
    RandSeed := s;
    Random;
    i := Length(Result);
    Result := Mathe.Produkt(Result, d);
    Result := Mathe.Quotient(Result, Mathe.Potenz('10', IntToStr(i)));
    Result := Mathe.Summe(Result, von);
  End;

Function Zufallszahl(Const von, bis: MatheString): MatheString;
  Var d, r: String;
    s, i:  Integer;

  Begin
    If von > bis Then System.Error(reRangeError);
    d := bis - von + 1;
    SetLength(r, Length(d) * 2 + 33);
    s := RandSeed;
    For i := Length(r) downto 1 do r[i] := Char(Random(10) + Ord('0'));
    RandSeed := s;
    Random;
    Result := ((MatheString(r) * d) div Power('10', Length(r))) + von;
  End;
muß aber noch etwas dran arbeiten
Wollte ich gestern eigentlich noch nicht Posten, weil ich dachte die Verteilung sei sch****,
aber anscheinend ist sie garnicht soooo schlecht :D

Delphi-Quellcode:
a: MatheString;
i, i2: Integer;
X: Array of Integer;
S: String;

Memo1.Lines.BeginUpdate;
Try
  SetLength(X, 10001);
  ZeroMemory(@X[0], Length(x) * SizeOf(Integer));
  For i := 0 to 100000 do Begin
    a := Zufallszahl('1000', '10000');
    Memo1.Lines.Add(a);
    i2 := Integer(a);
    If (i2 < 1000) or (i2 > 10000) Then ASM INT 3 End;
    Inc(X[i2]);
  End;
  Memo1.Lines.Add('*******************');
  S := '';
  For i := 0 to High(X) do Begin
    If i mod 1000 = 0 Then Begin
      Memo1.Lines.Add(S);
      S := '*** ' + IntToStr(i) + ': ';
    End;
    If X[i] <= 26 Then S := S + Char(X[i] + Ord('A')) Else S := S + '*';
  End;
  Memo1.Lines.Add(S);
Finally
  Memo1.Lines.EndUpdate;
End;
Zitat:

1979
1998
5600
1460
5546
1454
7346
7035
7904
3672
3967
...
4897
6790
9679
1867

*** 0: AAAAAAAAAAAAAAAA...AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAA
*** 1000: NRMPHJXHKLOMKNII...LGMQKNMPNJLNMLPFLPGHMOJGPIQSOMJ NKNOGLGINMNNKH
*** 2000: NLLMMEMMHJGKMNLM...KJLLIOOMOJHJPIUJKNLFJGOHHKNJIOH PHJMJKJMQHNLJJ
*** 3000: JIJOQQHNMPNILGLL...LJKLIOIHJPJOKPNNOJLQMMKJOFNRQHH QJLJMNJEPFQODR
*** 4000: LKULFJIIQOMKONNG...OOJJNLIMFIQLKHHJEHGSFLJMXNLLHML OLFNPJHISNLKMK
*** 5000: IIJKKPPJHKILLKKG...QTNOJILMONJNLMNLNLNJNJNJRJHNOMI IQRKIPMKPPJILK
*** 6000: KKNHHMLKMMKFKPNK...KTNILNJPINIIKJINLJGQLNOLLMGKJKL JNLJNURLIOKOUM
*** 7000: UMNSNKNJOOJIJKSH...IJOELOJNNGGJNHLKNKLPJMRNQQJNHRO GLKKMKLMNLKIPM
*** 8000: OJMJHOJKKIHPMINK...GJQHHGFNMKNPNLLJKLKJJLIOQKIPLLF HJTMJQSMMIJOII
*** 9000: NRMIQNMMMILQJLNG...KNKJMLNTLPJOJKINLHQGMFMLIOMLQSG ONMIJPFHIQOQIL
*** 10000: A
A = kein Wert | B = ein Mal gefunden | C = 2 ....
und wie ich grad seh, ist die 10000 auch nicht besetzt, also
Delphi-Quellcode:
X := Zufallszahl('1000', '10000');
entspricht nur 1.000 <= X < 10.000

ich füg also nich ein INC hinzu, werd' es einbauen und dann die nächsten Minuten irgendwann alles hochladen


hab auch grad noch 'nen Fehler in Mathe.Vergleich gefunden,
da stannd z.B. If Length(a) < Length(a), was natrülich nicht so das gewünschte Ergebnis brachte :nerd:

himitsu 16. Jun 2009 08:28

Re: Mathe mit Strings (die deutsche StringMatheLib ._. )
 
Zitat:

Zitat von himitsu
und wie ich grad seh, ist die 10000 auch nicht besetzt, also

OK, es hatte doch richtig gerechnet ... nur das Ergebnis wurde vorhin falsch angezeigt :wall:

Das mit der Units Types hab ich jetzt erstmal einfach mit dem {$IF}-Problem verknüpft und es darüber abgeschaltet :angel2:

ja und wegen dem Error <> Exception:
Da man ja auch ohne SysUtils arbeiten kann und somit dann Exception nicht zur Verfügung stünde,
wird der Fehler über (Run)Error abgesetzt.
Und sobald die SysUtils auch nur irgendwo im Programm vorhanden ist, werden diese Fehlercodes dann an die passenden Exceptions weitergeleitet. :angel:

Bin gespannt, ob es nun auch in D5 läuft.

[add]
In den Festpunktzahlen hat nun jede Variable sicherheitshalben einen eigenen internen Wert für die Nachkommastellen,
falls da mal wer mittendrin den globalen Wert für die maximalen Nachkommastellen ändert :shock:

[add]
Und wegen dem zusätzlichem undn unglücklich Positioniertem Edit in Demo 3 nicht wundern.
Bin grad etwas am Testen, was das Rundungsverhalten bei den Rechenoperationen betrifft.

qwertz543221 16. Jun 2009 10:50

Re: Mathe mit Strings (die deutsche StringMatheLib ._. )
 
zur random funktion:

wo wird denn die variable "randseed" initialisiert / deklariert?

in deiner function zufallszahl(mathe:tmathe;const von, bis:string):string; wird sie zwar genutzt aber nicht deklariert.


hab ich vlt ein update der Tmathe verpasst?

GPRSNerd 16. Jun 2009 10:54

Re: Mathe mit Strings (die deutsche StringMatheLib ._. )
 
Randseed ist aus der Unit "System".

himitsu 16. Jun 2009 11:33

Re: Mathe mit Strings (die deutsche StringMatheLib ._. )
 
Jupp, ich nutze praktisch für die "kleineren" Einheiten den Zufallsgenerator von Delphi, aus der Unit System.

Und falls sich wer fragt, warum ich da RandSeed auslese und vorallem warum es dann wieder zurückgesetzt wird:
Das ist, damit die Gleichverteilung der Zufallszahlen erhalten bleibt und der Generator nicht durch die "vielen" Aufrufe von Random unnötig gestört wird.
Praktisch nutze ich zwar Random mehrfach pro Zufallszahl, aber effektiv wird die Funktion nur einmal aufgerufen.

qwertz543221 16. Jun 2009 11:36

Re: Mathe mit Strings (die deutsche StringMatheLib ._. )
 
ok danke für die info.
ich dachte das sei vlt. eine eigene var / const für diese funktion.

sirius 16. Jun 2009 12:13

Re: Mathe mit Strings (die deutsche StringMatheLib ._. )
 
Ich habe mal folgende Ergänzung gemacht (für alle, die keine class operators nutzen können):
Delphi-Quellcode:
Unit StringMatheLib;
//ich tippe hier nur die Ergänzungen, alles andere von himi sollte man beibehalten

interface

uses Variants;


type

  TMatheVarData = packed record
    VType: TVarType;
    Reserved1, Reserved2, Reserved3: Word;
    Mathe: String; //Man könnte hier auch TMathe drin speichern und den String in die Klasse legen, wäre etwas elegenater und sicherer, da man mit der automatischen Verwaltung der Strings nicht kollidieren kann. Ich wollte nur grad die Klasse TMathe nicht umschreiben.
    Reserved4: LongInt;
  end;


  TMatheVariant=class(TCustomVariantType)
   public
    procedure BinaryOp(var Left: TVarData; const Right: TVarData; const Operator: TVarOp); override;
    procedure UnaryOp(var Right: TVarData; const Operator: TVarOp); override;
    function CompareOp(const Left, Right: TVarData; const Operator: TVarOp): Boolean; override;
    procedure Compare(const Left, Right: TVarData; var Relationship: TVarCompareResult); override;
    procedure Cast(var Dest: TVarData; const Source: TVarData); override;
    procedure CastTo(var Dest: TVarData; const Source: TVarData; const AVarType: TVarType); override;
    procedure Clear(var V: TVarData); override;
    procedure Copy(var Dest: TVarData; const Source: TVarData; const Indirect: Boolean); override;
    function IsClear(const V: TVarData): Boolean; override;
   protected
    function LeftPromotion(const V: TVarData; const Operator: TVarOp; out RequiredVarType: TVarType): Boolean; override;
    function RightPromotion(const V: TVarData; const Operator: TVarOp; out RequiredVarType: TVarType): Boolean; override;
  end;


  function VarMatheCreate:Variant; overload;
  function VarMatheCreate(const Init:string):Variant; overload;
  function VarMatheCreate(const Init:Integer):Variant; overload;

implementation


var TempMatheVariant:TMatheVariant=nil;
    Mathe:TMathe=nil;


function VarMatheCreate(const Init:string):Variant;
begin
  VarClear(Result);
  TMatheVarData(Result).VType:=TempMatheVariant.VarType;
  TMatheVarData(Result).Mathe:=Init;
end;
function VarMatheCreate:Variant;
begin
  result:=VarMatheCreate('0');
end;
function VarMatheCreate(const Init:Integer):Variant;
var s:string;
begin
  str(init,s);
  result:=VarMatheCreate(s);
end;




{ TMatheVariant }


procedure TMatheVariant.BinaryOp(var Left: TVarData; const Right: TVarData;
  const Operator: TVarOp);
var sRight:string;
begin
  if TMatheVarData(Left).VType<>TempMatheVariant.VarType then
    RaiseInvalidOp;
  if TMatheVarData(Right).VType=TempMatheVariant.VarType then
    sRight:=TMatheVarData(Right).Mathe
  else
    sRight:=VarToStr(Variant(Right));

  case Operator of
    opAdd:
      TMatheVarData(Left).Mathe:=Mathe.Summe(TMatheVarData(Left).Mathe,
                                             sRight);
    opSubtract:
      TMatheVarData(Left).Mathe:=Mathe.Differenz(TMatheVarData(Left).Mathe,
                                                 sRight);
    opMultiply:
      TMatheVarData(Left).Mathe:=Mathe.Produkt(TMatheVarData(Left).Mathe,
                                               sRight);
    opIntDivide:
      TMatheVarData(Left).Mathe:=Mathe.Quotient(TMatheVarData(Left).Mathe,
                                                sRight);
    opModulus:
      TMatheVarData(Left).Mathe:=Mathe.Modulo(TMatheVarData(Left).Mathe,
                                              sRight);
    else
      RaiseInvalidOp;
  end;
end;

procedure TMatheVariant.Cast(var Dest: TVarData; const Source: TVarData);
begin
  VarDataClear(Dest);
  fillchar(Dest,sizeof(dest),0);
  TMatheVarData(Dest).VType:=TempMatheVariant.VarType;
  if TMatheVarData(Source).VType=TempMatheVariant.VarType then
    TMatheVarData(Dest).Mathe:=TMatheVarData(Source).Mathe
  else
    TMatheVarData(Dest).Mathe:=VarToStr(Variant(Source));
end;

procedure TMatheVariant.CastTo(var Dest: TVarData; const Source: TVarData;
  const AVarType: TVarType);
var Temp:TVarData;
begin
  if TMatheVarData(Source).VType=TempMatheVariant.VarType then
  begin
    fillchar(temp,sizeof(temp),0);
    Temp.VType:=varstring;
    Temp.VString:=Pointer(TMatheVarData(Source).Mathe);
    VarDataCastTo(Dest,Temp,aVarType);
  end else
    inherited;
end;

procedure TMatheVariant.Clear(var V: TVarData);
begin
  if TMatheVarData(V).VType=TempMatheVariant.VarType then
  begin
    TMatheVarData(V).VType:=varEmpty;
    TMatheVarData(V).Mathe:='';
  end else
    inherited;
end;

procedure TMatheVariant.Compare(const Left, Right: TVarData;
  var Relationship: TVarCompareResult);
var sRight:string;
begin
  if TMatheVarData(Left).VType<>TempMatheVariant.VarType then
    RaiseInvalidOp;
  if TMatheVarData(Right).VType=TempMatheVariant.VarType then
    sRight:=TMatheVarData(Right).Mathe
  else
    sRight:=VarToStr(Variant(Right));

  case Mathe.Vergleich(TMatheVarData(Left).Mathe,sRight) of
    LessThanValue: RelationShip:=crLessThan;
    EqualsValue : RelationShip:=crEqual;
    GreaterThanValue : RelationShip:=crGreaterThan;
  end;
end;

function TMatheVariant.CompareOp(const Left, Right: TVarData;
  const Operator: TVarOp): Boolean;
var sRight:string;
    Art:TVergleich;
begin
  if TMatheVarData(Left).VType<>TempMatheVariant.VarType then
    RaiseInvalidOp;
  if TMatheVarData(Right).VType=TempMatheVariant.VarType then
    sRight:=TMatheVarData(Left).Mathe
  else
    sRight:=VarToStr(Variant(Right));

  Art:=vGleich;
  case Operator of
    opCmpNE:Art:=vUngleich;
    opCmpLT:Art:=vKleiner;
    opCmpLE:Art:=vKleinerGleich;
    opCmpGT:Art:=vGroesser;
    opCmpGE:Art:=vGroesserGleich;
  end;
  result:=Mathe.Vergleich(TMatheVarData(Left).Mathe,sRight,Art);

end;

procedure TMatheVariant.Copy(var Dest: TVarData; const Source: TVarData;
  const Indirect: Boolean);
begin
  if Indirect and VarDataIsByRef(Source) then
    VarDataCopyNoInd(Dest, Source)
  else
  begin
    TMatheVarData(Dest).VType:=TempMatheVariant.VarType;
    TMatheVarData(Dest).Mathe:=TMatheVarData(Source).Mathe;
  end;

end;

function TMatheVariant.IsClear(const V: TVarData): Boolean;
begin
  result:=TMatheVarData(V).Mathe='';
end;

function TMatheVariant.LeftPromotion(const V: TVarData;
  const Operator: TVarOp; out RequiredVarType: TVarType): Boolean;
begin
  result:=inherited LeftPromotion(V,Operator,RequiredVarType);
end;

function TMatheVariant.RightPromotion(const V: TVarData;
  const Operator: TVarOp; out RequiredVarType: TVarType): Boolean;
begin
  result:=inherited RightPromotion(V,Operator, RequiredVarType);
end;

procedure TMatheVariant.UnaryOp(var Right: TVarData;
  const Operator: TVarOp);
begin
  if Right.VType = VarType then
    case Operator of
      opNegate:
        Mathe.Negieren(TMatheVarData(Right).Mathe);
    else
      RaiseInvalidOp;
    end
  else
    RaiseInvalidOp;
end;

initialization

Mathe:=TMathe.Create;
TempMatheVariant:=TMatheVariant.Create;


finalization

TempMatheVariant.Free;
TempMatheVariant:=nil;
Mathe.Free;
Mathe:=nil;

End.
Damit geht dann auch folgendes (z.B. unter Delphi 7):
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var x,z:Variant;
begin
  x:=VarMatheCreate('1200000000000000000000000000'); //um eine Initialisierung kommt man nicht herum

  //aber dann:
  x:=x+'3';
  z:=x+1;
  z:=z*2;
  memo1.lines.add(-z);
end;

himitsu 16. Jun 2009 12:24

Re: Mathe mit Strings (die deutsche StringMatheLib ._. )
 
ab Delphi2006/TurboDelphi geht das zwar auch jetzt schon > MatheString aus StringMatheRec.pas

aber ich kann das gern ins nächste Update mit reinnehmen.
werd' es aber in eine eigene Unit legen > StringMatheVariant.pas vermutlich


PS: ich weiß nicht, ob man das merkt und es eventuell auch so rüberkommt,
aber mann muß immer nur die Unit einbinden, aus welcher man den gewünschten Typ nutzt, also

TMathe > StringMatheLib
MatheString > StringMatheRec
MatheStringX > StringMatheFloatRec (wobei ich mir grad überlegt hab das X wohl besser gegen ein F auszutauschen)

sirius 16. Jun 2009 12:34

Re: Mathe mit Strings (die deutsche StringMatheLib ._. )
 
Zitat:

Zitat von himitsu
ab Delphi2006/TurboDelphi geht das zwar auch jetzt schon > MatheString aus StringMatheRec.pas

Deswegen meinte ich ja: für alle, die keine Class Operators nutzen können (da ja so viele, wie ich, noch D7 nutzen).

Zitat:

aber ich kann das gern ins nächste Update mit reinnehmen.
werd' es aber in eine eigene Unit legen > StringMatheVariant.pas vermutlich
Ja kannst du. Aber ich denke, der Code hier reicht auch.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:54 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz