Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   DIV and MOD (https://www.delphipraxis.net/98012-div-mod.html)

dajuhsa 20. Aug 2007 18:00


DIV and MOD
 
Liste der Anhänge anzeigen (Anzahl: 2)
Guuuuuten Tag!

ich habe seit gestern ein wenig mit den Ausdrücken DIV und MOD experimentiert und heraus kam eine dll.
sie hat zwar wenig nutzen weil man das alles auch mit strings machen könnte aber trotzdem erklär ich mal ein paar methoden:
-GetDig -> sucht eine Ziffer in einem Integer
-GetLastDig -> gibt die letzte Ziffer zurück
-ChangeDig -> ändert Ziffer a in Zahl b zu Ziffer c um
-TrimDeg -> versucht einen Winkel möglichst klein zu machen:
Delphi-Quellcode:
begin
X := 850;  // X = 850
TrimDeg(X); // X = 130
end;
-TrimRad -> Das gleiche
Delphi-Quellcode:
begin
X := 5.2;  // X = 5.2
TrimRad(X); // X = 1.2
ihr seht ja schon, dass das ganze hauptsächlich irgendwas mit ziffern macht
Bitte guckt es euch an und sagt mir, wenn ihr Fehler entdeckt.
Bittedankeschön

[edit=Luckie]Thread-Titel korrigiert, als ein Wort findet man das ja in der Suche nie. :wall: Mfg, Luckie[/edit]

Die Muhkuh 20. Aug 2007 18:16

Re: DIVandMOD
 
fast 90kb für so eine DLL? :shock:
Warum ist das meiste eine Procedure und keine Funktion?

dajuhsa 20. Aug 2007 18:21

Re: DIVandMOD
 
zu der größe kann ich nix sagen, meinee erste dll.
das meiste ändert ja zahlen also procedure. Inc ist auch eine prozedur oder?
ne idee wegen der größe an was das liegen könnte?

Thanatos81 20. Aug 2007 18:23

Re: DIVandMOD
 
Versuch mal so viel wie möglich aus den Uses rauszuschmeißen, falls noch nicht geschehen ;-)

dajuhsa 20. Aug 2007 18:25

Re: DIVandMOD
 
math brauch ich für power
sysutils und classes waren schon drin
das wars.
brauch ich classes nicht?

sirius 20. Aug 2007 19:25

Re: DIVandMOD
 
-classes brauchst du nicht
-wenn du inttostr durch die Prozedur "str" ersetzt, dann fällt auch sysutils raus
-da power bei dir nur mit natürlichen zahlen rechnet, kannst du auch math rausschmeissen und power durch eine forschleife o.ä. ersetzen

Edit:
z.B. dadurch kannst du alle Bibliotheken rausschmeissen
Delphi-Quellcode:
function inttostr(x:integer):string;
begin
  str(i,result);
end;

function power(x,y:integer):integer;
var i:integer;
begin
  result:=1;
  for i:=1 to y do result:=result*x;
end;
Es lohnt sich nicht, wegen zwei so läppischen Funktionen, den ganzen Balast dieser Units mitzunehmen (die math bindet wiederum die sysutils ein)

Edit2: Ansonsten finde ich es etwas übertrieben, sowas hier reinzustellen.
1. Der QC haut ja nun keinen vom Hocker. Sowas hat doch 99% der Pascal-Nutzer innerhalb von wenigen sekunden, ohne groß nachzudenken geschrieben
2. Würde ich dafür nicht extra eine DLL hochladen.
==> Es ist sicherlich schön und sehr gut für dich zum üben :zwinker: , aber man muss nicht jeden "Furz" veröffentlichen.

Und Letztens: Warum nimmst du stdcall? Gerade bei den Funktionen lohnt sich ja register erst.

inherited 20. Aug 2007 19:33

Re: DIVandMOD
 
Statt Proceduren solltest du Funktionen benutzen, wenn man beispielsweise nur wissen möchte, was rauskommt ohne gleich die gesamte Variable zu ändern, zB
Delphi-Quellcode:
  if TrimRad(x)>5 then

dajuhsa 20. Aug 2007 20:10

Re: DIVandMOD
 
OK! ich hab das jetzt mal mit Funktionen erweitert. siehe erster Post :mrgreen:

semo 20. Aug 2007 20:17

Re: DIVandMOD
 
und wie groß isse nun die dll?

dajuhsa 20. Aug 2007 20:27

Re: DIVandMOD
 
88 Kilo wenn man der delphipraxis glauben schenkt :mrgreen:

semo 20. Aug 2007 20:47

Re: DIVandMOD
 
wenn du die sysutils noch raus kickst aus der uses section,
dann sparst du noch mal 8 kb, also insgesamt dann 80 kb.

du musst dann halt nur noch die funktion inttostr aus den sysutils in deine dll kopieren...

CalganX 20. Aug 2007 20:49

Re: DIVandMOD
 
Warum eigentlich eine DLL? Eine normale Unit würde es doch auch tun. Und wenn du den Quellcode nicht herausgeben willst, kannst du ja auch immer noch nur die DCU herausgeben. Ich finde eine DLL für sowas, was eigentlich nur Spielerei ist, total übertrieben.

Christopher

semo 20. Aug 2007 20:50

Re: DIV and MOD
 
spielerei, darum geht es ihm ja denke auch.
jeder fängt mal klein an oder?

dajuhsa 20. Aug 2007 20:59

Re: DIVandMOD
 
Zitat:

Zitat von CalganX
Warum eigentlich eine DLL? Eine normale Unit würde es doch auch tun. Und wenn du den Quellcode nicht herausgeben willst, kannst du ja auch immer noch nur die DCU herausgeben. Ich finde eine DLL für sowas, was eigentlich nur Spielerei ist, total übertrieben.

Christopher

is halt meine erste dll und ich glaub auch nicht dass die jemals ernsthaft eingesetzt wird, deshalb auch kein ernsthaftes format.
mein code is ja dabei und eigentlich wollt ich nur mal sehen ob das bei mir als dll überhaupt klappt

sirius 20. Aug 2007 21:04

Re: DIV and MOD
 
Du darfst nicht nur die Funktionen ergänzen, sondern musst auch die Unist aus der uses-Liste entfernen. Die tauchen in deiner DLL noch auf.
Ich hatte es unter 20kb.
Wobei der Vorteil noch dadurch vergrößert wird, dass nicht unnötig Klassen (z.B. Exception) durch die Units instanziert werden.

Khabarakh 20. Aug 2007 21:12

Re: DIVandMOD
 
Zitat:

Zitat von sirius
-da power bei dir nur mit natürlichen zahlen rechnet, kannst du auch math rausschmeissen und power durch eine forschleife o.ä. ersetzen

Power lässt sich ohne Math-Unit durch Exp() und Ln() ersetzen:
a^b = (e^ln a)^b = e^(b * ln a)

sirius 20. Aug 2007 21:30

Re: DIVandMOD
 
Zitat:

Zitat von Khabarakh
Zitat:

Zitat von sirius
-da power bei dir nur mit natürlichen zahlen rechnet, kannst du auch math rausschmeissen und power durch eine forschleife o.ä. ersetzen

Power lässt sich ohne Math-Unit durch Exp() und Ln() ersetzen:
a^b = (e^ln a)^b = e^(b * ln a)

Ja, das ist zwar richtig, aber weist du wie lange die FPU rattert, eh sie etwas mit der eulerschen Zahl zustande gebracht hat. Da ist (wie gesagt: natürliche Zahlen!) eine for schleife bedeutend schneller.

dajuhsa 20. Aug 2007 21:39

Re: DIV and MOD
 
@Khabarakh: Aha!! - Das versteh ich nicht...
@sirius: ich glaub ich lass es jetzt einfach is auch egal

sirius 20. Aug 2007 21:57

Re: DIV and MOD
 
Ich dachte du wolltest dazulernen :zwinker:, dafür sind wir doch hier :dp:

Was K. gemeint hat, kommt aus den Logarithmengesetzen. Ist keine Zauberei. (und wenn du 13 bist, dann hab Geduld, das kommt noch in der Schule).
So macht es auch die Unit math. Bzw. so hat man es früher selber implemtiert als man noch keine Unit math hatte. Damit kann man quasi x^y für alle reellen Zahlen (mit x>0) rechnen. günstiger für die FPU wäre IMHO x^y = 2^(x*lb(a)). Aber für deine Anwendung ist das alles overkill. Vermeide Fleißkommazahlen (single,double,real,extended) solange es geht!

dajuhsa 20. Aug 2007 22:13

Re: DIV and MOD
 
ja ich will auch lernen aber ich finde die sysutils.pas nicht^^
außerdem fällt mir nichts mehr ein was ich noch machen könnte weil auf optimierung hab ich keine lust wenn es nur ums lernen geht^^
nochwas:
meinst du nicht Fließkommazahl?
was ist schneller? Mein ChangeDig oder irgendwas mit strings und inttostr?

sirius 20. Aug 2007 22:18

Re: DIV and MOD
 
Ja meine ich...

Stringoperationen sind nicht die schnellsten, ... hmm schwer da ne Aussage zu treffen. Das müsste man testen.

Khabarakh 20. Aug 2007 22:50

Re: DIV and MOD
 
[OT]
Zitat:

Zitat von sirius
günstiger für die FPU wäre IMHO x^y = 2^(x*lb(a)).

Nachdem ich einmal so frei war, auf der rechten Seite deines Terms x durch y und a durch x zu ersetzen :mrgreen: (und natürlich den ld durch ln x / ln 2), blieb der Basis-2-Ansatz 5% hinter dem ersten zurück. Lassen wir den kürzeren Code gewinnen :zwinker: .
[/OT]

@dajuhsa: Vielleicht bin ich in der Minderheit, aber ich würde als 1. Ziffer jene am Weitesten rechts bezeichnen, da ihre Wertigkeit die niedrigste ist. Vor allem aber sparst du dir mit dieser Zählweise den IntToStr-Aufruf ;) (den man sowieso wieder durch einen eleganteren Logarithmus ersetzen könnte, aber das nur am Rande; denn in Punkto Performance ändert sich nichts).

sirius 21. Aug 2007 08:47

Re: DIV and MOD
 
Zitat:

Zitat von Khabarakh
Nachdem ich einmal so frei war, auf der rechten Seite deines Terms x durch y und a durch x zu ersetzen :mrgreen:

Nach 10 Uhr sollte man in meinem Alter keine Mathematik mehr machen :oops:
Zitat:

Zitat von Khabarakh
(und natürlich den ld durch ln x / ln 2)

Na, das war ja nicht der Sin (aus zwei Funktionen drei Funktionen machen). Das dauert natürlich länger. Es geht darum, dass in der Zeit, in der man einmal exp(x) rechnet, man bereits komplett a^b hätte rechnen können (siehe dein anderer Thread).

Trotzdem ist man wenn man 10^N (im Bereich integer) rechnet, mit einer For-Schleife oder besser noch mit einem vorbelegten array besser dran (wenn man schon abkürzen will)

xZise 21. Aug 2007 10:34

Re: DIV and MOD
 
Hi @ all,
ich habe mich auch mal mit dem Thema auseinader gesetzt und habe eine "IntLength"-Funktion entworfen, welche ohne strings die Länge eines Integers bestimmen kann.
Delphi-Quellcode:
function IntLength(AInt : Integer) : Integer;
begin
  Result := 0;
  while AInt > 0 do
  begin
    AInt := AInt div 10;
    inc(Result);
  end;
end;
Ich habe mal ein Test gemacht: Bei mir braucht die string-Variante für 900.001 Durchläufe ~ 255 ms. Die IntLength-Variante jetzt schon nur ~ 188 ms.
Vielleicht kennt ihr eine Möglichkeit den obigen Code zu optimieren ;) Vielleicht mit ASM? Da müsste ich aber passen :) da für mich ASM im FoW liegt xD
Zusätzlich hier meine ExtLength-Variante:
Delphi-Quellcode:
function ExtLength(AExt : Extended) : Integer;
begin
  Result := IntLength(Trunc(AExt));
end;
Sie berechnet leider nicht die Nachkommastellen, allerdings weiß ich nicht ob man die mitdazu rechnet.
Ich werde mir mal überlegen wie man das hinkriegen könnte.

[edit]Ich habe mir jetzt mal überlegt: Ich könnte die Vorkommastellen abschneiden und dann solange multiplizieren bis ich keine Nachkommastellen mehr habe.
Also habe ich das so gelöst:
Delphi-Quellcode:
{ Returns the length of a float (e.g. ExtLength(4365.87) = 6) }
function ExtLength(AExt : Extended) : Integer;
var
  ABuf : Extended;
begin
  Result := IntLength(Trunc(AExt));
  ABuf := AExt - Trunc(AExt);
  while Trunc(ABuf) < ABuf do
  begin
    ABuf := ABuf * 10;
    inc(result);
  end;
end;
Das Problem scheint zu sein, dass ABuf nicht genau eine Ganzzahl ist. Deshalb klemmt er sich da in eine Endlosschleife. (Wenn Trunc(ABuf) = 87 und ABuf 87 ist, beendet er nicht die Schleife)[/edit]

MfG
xZise

PS: string: ~437 ms; extLength: ~250 ms

Khabarakh 21. Aug 2007 11:21

Re: DIV and MOD
 
Die Länge der Nachkommastellen kannst du nicht wirklich ermitteln, da du dort bei so gut wie jedem Wert auf eine Periode stoßen wirst - schließlich untersuchst du die Zahl zur Basis 10, gespeichert wird sie aber zur Basis 2. Du müsstest die Zahl erst in einem sinnvollen Maße runden, genau so, wie es FloatToStr macht.

[edit]Du kannst ja noch den mathematischen Weg testen. Wird wohl irgendwo zwischen den beiden anderen Methoden liegen.
Delphi-Quellcode:
function IntLength(const aInt : Integer) : Integer;
begin
  Result := Ceil(Log10(aInt)); // bzw. Trunc(Ln(aInt) / Ln(10)) + 1
end;
[/edit]

xZise 21. Aug 2007 11:52

Re: DIV and MOD
 
Zitat:

Zitat von Khabarakh
Die Länge der Nachkommastellen kannst du nicht wirklich ermitteln, da du dort bei so gut wie jedem Wert auf eine Periode stoßen wirst - schließlich untersuchst du die Zahl zur Basis 10, gespeichert wird sie aber zur Basis 2. Du müsstest die Zahl erst in einem sinnvollen Maße runden, genau so, wie es FloatToStr macht.

[edit]Du kannst ja noch den mathematischen Weg testen. Wird wohl irgendwo zwischen den beiden anderen Methoden liegen.
Delphi-Quellcode:
function IntLength(const aInt : Integer) : Integer;
begin
  Result := Ceil(Log10(aInt)); // bzw. Trunc(Ln(aInt) / Ln(10)) + 1
end;
[/edit]

Naja... Die erste Variante braucht zwar weniger Zeit, aber auch die math-Unit, welche ja versucht wird zu verbannen ;)
Und das Ceil ist ja nichts anderes als "Trunc() + 1" oder?

Meine Frage ist, wo kann man den Logaritmus so optimieren (in richtung Log10) gegenüber ln? Weil an sich machen ja beide das gleiche (Also das bei Ceil() und Trunc()).

Und zu den Extended: Da müsste man sich also mit den Vorkammastellen zufriedengeben... Oder?

[edit]Ehm...
Trunc() + 1 ist bis zu 100 ms schneller als Ceil() o.O
Delphi-Quellcode:
function IntLength3(const aInt : Integer) : Integer;
begin
  Result := Trunc(Log10(aInt)) + 1; // bzw. Trunc(Ln(aInt) / Ln(10)) + 1;
end;
Das ist der gewinner mit nur 79 ms um 900.000 berechnungen durchzuführen![/edit]

[edit]Wenn man nur die Log10()-Methode aus der math.pas kopiert funktionierts auch ohne uses. Aber ich glaube Borland sieht das nicht gerne oder? Vielleicht könnte man es legalisieren?[/edit]

FAlter 21. Aug 2007 12:25

Re: DIV and MOD
 
Hi,

Zitat:

Zitat von [user
xZise[/user]][edit]Wenn man nur die Log10()-Methode aus der math.pas kopiert funktionierts auch ohne uses. Aber ich glaube Borland sieht das nicht gerne oder? Vielleicht könnte man es legalisieren?[/edit]

Evtl. von FreePascal/Lazarus kopieren?

Mfg
FAlter

Khabarakh 21. Aug 2007 12:53

Re: DIV and MOD
 
Zitat:

Zitat von xZise
Meine Frage ist, wo kann man den Logaritmus so optimieren (in richtung Log10) gegenüber ln?

Hast du wirklich gemessen, dass Log10 schneller ist als Ln? Bei dem zweiten Ansatz kommt schließlich noch die Division hinzu.
Zitat:

Und zu den Extended: Da müsste man sich also mit den Vorkammastellen zufriedengeben... Oder?
Fällt dir ein Problem ein, das die Anzahl der Nachkommastellen benötigt? Mir jedenfalls nicht. Dass nur für die Vorkammastellen ein mathematischer Operator (eben log10) existiert, spricht auch dafür, dass das Ermitteln der "letzten Nachkommastelle" unwichtig ist.
Zitat:

Trunc() + 1 ist bis zu 100 ms schneller als Ceil() o.O
Jopp, in Ceil steckt noch ein wenig mehr Logik, als ich dachte. Weshalb es sogar falsche Ergebnisse liefert *g* . Trunc() + 1 ist also die schnellste und einzige richtige Lösung.
Zitat:

[edit]Wenn man nur die Log10()-Methode aus der math.pas kopiert funktionierts auch ohne uses. Aber ich glaube Borland sieht das nicht gerne oder? Vielleicht könnte man es legalisieren?[/edit]
Ich denke, diese 5 Zeilen Asm kann man als "offenes Geheimnis" bezeichnen ;) . Dürfte so auf der Schöpfungshöhe von RadToDeg liegen.

xZise 21. Aug 2007 13:25

Re: DIV and MOD
 
Zitat:

Zitat von Khabarakh
Zitat:

Zitat von xZise
Meine Frage ist, wo kann man den Logaritmus so optimieren (in richtung Log10) gegenüber ln?

Hast du wirklich gemessen, dass Log10 schneller ist als Ln? Bei dem zweiten Ansatz kommt schließlich noch die Division hinzu.

Naja. Kommt auf die sichtweise drauf an.
Ob log10 schneller als ln ist, weiß ich nicht.
Aber es gilt ja:
Code:
log10(X) = ln(X) / ln(10)
Also müsste man sagen: Das "ln"-Konstrukt ist langsamer als log10 liefert aber gleiche Ergebnisse. Und rein theoretisch müssten beide Operatioen gleich schnell ablaufen, da ich, um log10 zu simulieren, das "ln"-Konstrukt verwenden würde.
Aber den scheint nicht so zu sein, oder Borland hat den log10-Algorythmus optimiert, weil ja die... ehm Basis? ... immer gleich ist, und man irgendwo kürzen könnte.

Ich weiß aber nicht, ob sie auch einfach ein anderen Rechenweg verwenden.

Wegen Lazarus/OpenPascal: Ich besitze es nicht :) und kann deshalb auch keine aussage darüber machen.
Und nur deshalb das zu downloaden wäre etwas zu overkill :) Vielleicht gibt es jemand anderen, der den log10-Algorythmus posten kann. Ich könnte den in den Testprogramm integrieren.

MfG
xZise

[edit]omfg ... sry, aber es steht ja als Kommentar da:
Delphi-Quellcode:
{ Log.10(X) := Log.2(X) * Log.10(2) }
Meine, zwar noch auf math basieren, aber ggf. bald nicht mehr:
Delphi-Quellcode:
function Log10(const X : Extended) : Extended;
begin
  Result := Log2(X) * LogN(10, 2);
end;
[/edit]

sirius 21. Aug 2007 13:50

Re: DIV and MOD
 
Zitat:

Zitat von xZise
Code:
log10(X) = ln(X) / ln(10)

Und z.B. :mrgreen: :
Code:
ln(x)=log10(x) / log10(e)
Und nun? Das kann man immer weiter fortsetzen mit jeder beliebigen Basis

Es geht doch in dem Fall darum, was die FPU am schnellsten kann.

Du hast neben den 4 Grundrechenoperationen folgendes zur Verfügung:
- a * log2(b)
- (2^a) - 1 für -1 <= a <= +1
- a*2^(int(b))
Und natürlich noch runden, trigonometrische Funktionen und noch folgende Konstanten:
- pi
- log2(10)
- log2(e)
- log10(2)
- ln(2)

Edit: Demnach bekommt man log10 und log2 recht schnell hin und für alle anderen Basen braucht man die doppelte Zeit.
Edit: ln auch :mrgreen:

xZise 21. Aug 2007 18:07

Re: DIV and MOD
 
Allerdings sind Divisionen langsamer als Multiplikationen.
Deshalb ist (wahrscheinlich) die Multiplikationsvariante schneller...
Es geht nur darum die Unit math rauszuhauen.

fLaSh11 21. Aug 2007 20:11

Re: DIVandMOD
 
Zitat:

Zitat von dajuhsa
is halt meine erste dll und ich glaub auch nicht dass die jemals ernsthaft eingesetzt wird, deshalb auch kein ernsthaftes format.

Mal ehrlich... ist das jetzt ein Scherzthread? :mrgreen:


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:42 Uhr.

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