![]() |
Re: DIV and MOD
Ja meine ich...
Stringoperationen sind nicht die schnellsten, ... hmm schwer da ne Aussage zu treffen. Das müsste man testen. |
Re: DIV and MOD
[OT]
Zitat:
[/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). |
Re: DIV and MOD
Zitat:
Zitat:
![]() 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) |
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:
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.
function IntLength(AInt : Integer) : Integer;
begin Result := 0; while AInt > 0 do begin AInt := AInt div 10; inc(Result); end; end; 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:
Sie berechnet leider nicht die Nachkommastellen, allerdings weiß ich nicht ob man die mitdazu rechnet.
function ExtLength(AExt : Extended) : Integer;
begin Result := IntLength(Trunc(AExt)); end; 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:
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]
{ 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; MfG xZise PS: string: ~437 ms; extLength: ~250 ms |
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:
[/edit]
function IntLength(const aInt : Integer) : Integer;
begin Result := Ceil(Log10(aInt)); // bzw. Trunc(Ln(aInt) / Ln(10)) + 1 end; |
Re: DIV and MOD
Zitat:
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:
Das ist der gewinner mit nur 79 ms um 900.000 berechnungen durchzuführen![/edit]
function IntLength3(const aInt : Integer) : Integer;
begin Result := Trunc(Log10(aInt)) + 1; // bzw. Trunc(Ln(aInt) / Ln(10)) + 1; end; [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] |
Re: DIV and MOD
Hi,
Zitat:
Mfg FAlter |
Re: DIV and MOD
Zitat:
Zitat:
Zitat:
Zitat:
|
Re: DIV and MOD
Zitat:
Ob log10 schneller als ln ist, weiß ich nicht. Aber es gilt ja:
Code:
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.
log10(X) = ln(X) / ln(10)
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:
Meine, zwar noch auf math basieren, aber ggf. bald nicht mehr:
{ Log.10(X) := Log.2(X) * Log.10(2) }
Delphi-Quellcode:
[/edit]
function Log10(const X : Extended) : Extended;
begin Result := Log2(X) * LogN(10, 2); end; |
Re: DIV and MOD
Zitat:
Code:
Und nun? Das kann man immer weiter fortsetzen mit jeder beliebigen Basis
ln(x)=log10(x) / log10(e)
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: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:55 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz