Fixpoint - library bzw. sinnvolles Vorgehen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von Winni »

Hi!

Na, da zeigst Du gleich noch einmal dass Du von Fließkomma nix verstehst.
Wenn Du das lernen möchtest, dann sieh Dir in der unit math mal die function isZero an.
Dann kannst Du ja vielleicht qualifiziert mitreden.

Wo steht es, dass ich verpflichtet bin nach dem Stand der Kunst zu arbeiten?
Wer definiert, was der Stand der Kunst ist?
War der Lehmann Crash nach dem Stand der Kunst?
Vermutlich ja, denn die Banker sind ja zu dumm zum Runden.

Ich hätte nur gerne eine korrekte Zahl. Und keine Fixkomma-Berechnungen.

Winni

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von Warf »

Winni hat geschrieben:Hi!

Na, da zeigst Du gleich noch einmal dass Du von Fließkomma nix verstehst.
Wenn Du das lernen möchtest, dann sieh Dir in der unit math mal die function isZero an.
Dann kannst Du ja vielleicht qualifiziert mitreden.


Ok, benutz ich halt isZero:

Code: Alles auswählen

program Project1;
 
{$mode objfpc}{$H+}
 
uses math;
 
var Kontostand: Double;
  i: Integer;
const
  Einnahme: Double = 0.1;
  Ausgabe: Double = 0.3;
  Iterations: Integer = 1000;
begin
  Kontostand:=0;
  for i:=1 to Iterations*3 do
    Kontostand += Einnahme;
  for i:=1 to Iterations do
  begin
    if (Kontostand < Ausgabe) and not IsZero(Kontostand - Ausgabe) then
      Writeln('Buchung fehlgeschlagen')
    else
      Kontostand -= Ausgabe;
  end;
  WriteLn(Kontostand);
end.


Immernoch kaputt, zugegegeben, nicht mehr mit nur 3 rechnungen, sondern erst mit 3000. Aber kein Problem, welche Finanzsoftware muss schon 3000 berechnungen machen. Vielleicht habe ich es aber immernoch "falsch verstanden" und double ist tatsächlich perfekt, solang damit nicht gerechnet wird

Winni hat geschrieben:Wo steht es, dass ich verpflichtet bin nach dem Stand der Kunst zu arbeiten?
Wer definiert, was der Stand der Kunst ist?

Stand der Technik ist ein Juristisch definierter begriff. Ich selbst bin kein jurist, aber die uni Münster schreibt zur Haftung bei IT-Projekten (Link):
Gewährleistung beim Kaufvertrag, Werkvertrag
§§ 434, 633 BGB
Mangel, wenn die Leistung nicht:
die vereinbarte Beschaffenheit: idR gemäß Pflichtenheft, Spezifikation,
eine Eignung zur vorausgesetzten Verwendung,
sonst: die übliche Beschaffenheit (Stand der Technik) aufweist


Und für die Erhebung des Pflichtenhefts steht:
Fehlt eine exakte Definition der Leistung schuldet der Auftragnehmer ein Werk, „das dem Stand der Technik bei mittlerem Ausführungsstandard“ (ein Werk mittlerer Art und Güte) entspricht. Dadurch können dem Auftragnehmer mehr, aber auch weniger Pflichten, als ursprünglich gedacht, auferlegt werden

Wenn ein aspekt also nicht gesondert vereinbart ist (z.B. Pflichtenheft) hast du zwei möglichkeiten, entweder du hast nen guten Grund warum du es anders machst (ein Grund der im schlimmsten Fall vor Gericht standhalten muss) oder du hälst dich an den Stand der Technik. Allein weil einen Grund vorzuweisen generell mehr aufwand ist als einfach nachzuweisen das man sich an den Stand der Technik gehalten hat, ist es empfehlenswert sich dran zu halten. Wenn man sich nicht dran hält und keine stichfeste argumentation hat (z.b. jemand liest deinen kommentar das man doch Double nehmen soll und argumentiert dann mit "jemand im internet hat das so gesagt), ist das ein Mangel.

Winni hat geschrieben:Ich hätte nur gerne eine korrekte Zahl. Und keine Fixkomma-Berechnungen.

Ja ich hätte auch gerne korrekte zahlen, und genau deswegen ist IEEE 754 eine beschissene Idee.

Übrigens, hier geht es weder um fixpunkt noch fließpunkt darstellung, sondern um die Tatsache das IEEE 754 Zahlen exponenten im zweiersystem haben, Finanzsysteme allerdings im Dezimalsystem arbeiten, und sich daher viel zahlen nicht ohne rundungsfehler darstellen lassen.
Dezimal-Fließpunkt-Arithmetik wäre hingegen akzeptabel, sogar präferabel im gegensatz zu Dezimal Fixpunkt darstellung, allerdings ist das deutlich komplexer, was sich massiv auf die Laufzeit auswirkt und daher wird im Finanzsektor fast ausschließlich fixpunktarithmetik verwendet, mit einer "ausreichenden" genauigkeit (10^-4).

Das Fließpunktarithmetik genauer sein kann als Fixpunktarithmetik (solang die mantisse die selbe länge hat) ist klar, darum geht es hier aber nicht, es geht um Fließpunktberechnung im 2er System vs Fixpunktberechnung im 10er System.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von af0815 »

Schöner Artikel in Deutsch dazu hier https://www.punkt-akademie.de/wp-conten ... mputer.pdf mit allgemeinen Informationen.

@winni: Die Problematik ist dann zu verstehen, wenn man als Dienstleister Software schreiben darf. Dann muss man sich ganz genau überlegen auf was man sich einlässt. Recht, Finanzmathematik und Mathematik passen nicht wirklich gut zusammen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Lemmy
Beiträge: 57
Registriert: Do 23. Feb 2017, 06:18

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von Lemmy »

Hallo zusammen,

erst mal Danke an alle Beteiligten. Die Hinweise zur Berechnung auf der CPU, die Infos von Winni bzgl. Berechnung mit Currency (DIV),... waren sehr hilfreich, das zu bestätigen was ich vermutet habe

hier nochmal die Fakten:

aktuell wird die Berechnung in Double ausgeführt. Die Berechnung läuft nach dem CSV Import, weil die Berechnung nicht nur auf den neu eingespielten Daten basiert sondern auch auf den Bestandsdaten. Diese Berechnung zu optimieren nerv ich den Auftraggeber nun schon erfolglos mehrere Jahre, mein Wunsch wäre das Zeugs in einen Thread zu verpacken und dann mehrere Threads loslaufen zu lassen - hätte auch den Vorteil, dass ich die Berechnung dann auch endlich unit-testbar machen kann, es gäbe also einige Gründe, die Berechnung mal neu aufzustellen, es gab aber in den letzten Jahren halt wichtigeres, u.a. die Umstellung auf Lazarus/Linux.

@Winni
[zitat]
Da würde ich mir doch mal die Definition von currency durchlesen. Es hat vier (4!!) Nachkommastellen. Da tritt dann bei Deinem Loop schon innerhalb von 300 Durchläufen die Ungenauigkeit in der 3 Stelle auf, während Double kein FESTkomma ,hat sondern ein Fließkomma, also exact bleibt.

Die Definition von curreny ist hier: .
https://wiki.freepascal.org/Currency/de

Hoffentlich habt ihr nicht all die letzten Jahre falsche Werte mittels currency berechnet.
[/zitat]

so einfach ist das aber nicht, teilweise haben schon andere darauf hingewiesen:
es mag sein, dass Double an der 4. Stelle genauer ist - wenn die Beredchnung aber mit max. 4 Nachkommastellen durchgeführt werden soll, dann stimmt das Ergebnis halt nicht mehr, wenn ich mit mehr als 4 Nachkommastellen rechne (daher auch mein Hinweis in dem Post, dass ich unfair bin). Da laufen dann diese Differenzen in Folge einfach entsprechend auf - das typische Rundungsproblem in der Mathematik - bzw. dass man zwischenergebnisse halt nicht runden soll. Und wenn jetzt der Auftraggeber mir ins "Pflichtenheft" schreibt: Berechnung mit 4 Nachkommastellen, dann steht das da erst mal.


Ich habe das Testprojekt auch mal mit INT64 rechnen lassen - das wäre dann schon deutlich schneller (auch als Double), wenn ich nur zu Beginn und Ende einmal die Daten "konvertiere", d.h. mit 10000 multipliziere / dividiere. Allerdings führt das Vorgehen bei Multiplikationen und Divisionen eben zu nicht ganz trivialem Verhalten :-) Daher meine Frage nach einer Lib, die hier unterstützt

Danke nochmal an alle!

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von wp_xyz »

Lemmy hat geschrieben:Laufzeit bei größeren Importen liegt bei 4-6h

Vielleicht bin ich naiv, weil ich nicht vom Fach bin, aber ich kann mir außer Rechnungen in der Quantenmechanik oder für Finite Element-Simuationen kaum etwas vorstellen, was so lang rechnet. Ich denke, da ist etwas anderes faul, und der Unterschied float/currency ist nebensächlich.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von Warf »

wp_xyz hat geschrieben:Vielleicht bin ich naiv, weil ich nicht vom Fach bin, aber ich kann mir außer Rechnungen in der Quantenmechanik oder für Finite Element-Simuationen kaum etwas vorstellen, was so lang rechnet. Ich denke, da ist etwas anderes faul, und der Unterschied float/currency ist nebensächlich.


Naja, wenn man so mehrere Milliarden berechnungen hat, kann man schon in diese gegend kommen. Und je nachdem wie viele multiplikationen macht, ist da schon n gewaltiger unterschied zwischen currency und double

Lemmy hat geschrieben:aktuell wird die Berechnung in Double ausgeführt. Die Berechnung läuft nach dem CSV Import, weil die Berechnung nicht nur auf den neu eingespielten Daten basiert sondern auch auf den Bestandsdaten. Diese Berechnung zu optimieren nerv ich den Auftraggeber nun schon erfolglos mehrere Jahre, mein Wunsch wäre das Zeugs in einen Thread zu verpacken und dann mehrere Threads loslaufen zu lassen - hätte auch den Vorteil, dass ich die Berechnung dann auch endlich unit-testbar machen kann, es gäbe also einige Gründe, die Berechnung mal neu aufzustellen, es gab aber in den letzten Jahren halt wichtigeres, u.a. die Umstellung auf Lazarus/Linux.

Wie gesagt, meines erachtens nach macht Threading da als einziges Sinn Fixpunktberechnungen sind nunmal aufwändiger als Double berechnungen (da double über das Multiplikationswerk in der Arithmetikunit der CPU berechnet werden, während Fixpunktmathematik per software Implementiert wird, und Hardware ist schneller als software).
Ansonsten, was für ne Optimierungstufe benutzt du denn? Vielleicht kannst du damit noch ein paar % rausholen, und ansonsten wie gesagt, LLVM ist was optimierung von Mathematischen Berechnungenen angeht ziemlich gut (soweit ich weiß wurde auf dem trunk einiges an Fortschritt bezüglich LLVM gemacht).

Lemmy hat geschrieben:Ich habe das Testprojekt auch mal mit INT64 rechnen lassen - das wäre dann schon deutlich schneller (auch als Double), wenn ich nur zu Beginn und Ende einmal die Daten "konvertiere", d.h. mit 10000 multipliziere / dividiere. Allerdings führt das Vorgehen bei Multiplikationen und Divisionen eben zu nicht ganz trivialem Verhalten :-) Daher meine Frage nach einer Lib, die hier unterstützt

Danke nochmal an alle!


Mal zu ner erklärung wie Fixpunktarithmetik funktioniert, bzw. erstmal wie Fließpunktarithmetik funktioniert (Fixpunktarithmetik ist einfach ein Sonderfall von Fließpunktarithmetik bei dem man nach jeder Berechnung den Exponenten normalisiert).
Erst mal an Hand eines Beispiels:
Multiplikation:

Code: Alles auswählen

1,5 * 1,25 = 1,875
wobei
15*125 = 1875

Die Kommastelle im ergebnis ist also genau die anzahl kommastellen der beiden Faktoren Multipliziert.
Addition:

Code: Alles auswählen

1,5 + 1,25 = 1,75
wobei
150 + 125 = 175

Man muss also die zahl mit weniger kommastellen auf die anzahl der anderen zahl erweitern, und dann ist das auch die anzahl der kommastellen des ergebnisses.

Formal: Eine Kommazahl besteht aus Matisse m und Exponent e (als basis nehmen wir 10), also 1,5 ist die mantisse 15 und der exponent -1. Also

Code: Alles auswählen

1,5 = 15*10^(-1) 
und
1,25 = 125*10^(-2)

Dann folgt

Code: Alles auswählen

1,5*1,25 
= 15*10^(-1) * 125*10^(-2)
=* 15*125*10^(-1 + -2)
= 15*125*10^(-3)
= 1875*10^(-3)
= 1,875

Wie bereits vorher beobachtet wird bei der gleichung mit * der exponent addiert. Allgemein

Code: Alles auswählen

m1*10^(e1) * m2*10^(e2) = m1*m2 * 10^(e1 + e2)

Addition:

Code: Alles auswählen

15*10^(-1) + 125*10^(-2) 
=* 150*10^(-2) + 125*10^(-2)
=** (150 + 125) * 10^(-2)

Bei * multiplizieren wir 15 mit 10 und 10^(-1) teilen wir durch 10, multiplizieren den gesammten Term also mit 1, und bei ** wenden wir das distributivgesetz an.
Allgemein: Sei emin = min(e1, e2):

Code: Alles auswählen

m1*10^(e1) + m2*10^(e2) 
=* m1*10^(e1 - emin + emin) + m2*10^(e2 - emin + emin)
=** m1*10^(e1-emin)*10^(emin) + m2*10^(e2-emin)*10^(emin)
=*** (m1*10^(e1-emin) + m2*10^(e2-emin)) * 10^(emin)


Hier wird das minimum der beiden exponenten genommen, da der kleinste exponent die meisten nachkommastellen anzeigt (-5 => 5 nachkommastellen). Bei * wird einfach - emin + emin gerechnet, also + 0, und bei ** wird das dann auseinader gezogen, sodass bei *** dann wieder das distributivgesetz angewendet werden kann. Da emin entweder e2 oder e1 ist, wird eine der beiden zahlen mit 10^(0) = 1 multipliziert und muss daher nicht verändert werden.

Man sollte anmerken das das minimum zu nehmen in der Praxis eine beschissene Idee ist, da dann große Zahlen verloren gehen können, daher ist in der Praxis (z.B. bei IEEE 754 Zahlen) die Mantisse Links aligned (also immer von der form 1,... oder 0,...) und der maximale exponent wird gewählt. Für ein möglichst einfaches Beispiel mach ich es hier trozdem mal so

Fixpunktmathematik hat jetzt den vorteil das e = e1 = e2, im fall von currency also -4. Damit ist emin = e1 = e2, und damit kann man addition einfach so ausführen:

Code: Alles auswählen

m1*10^e + m2*10^e = (m1 + m2)*10^e

Somit ist die addition exakt die Integer addition. Bei der Multiplikation allerdings wird es interresant:

Code: Alles auswählen

m1*10^e * m2*10^e = m1*m2*10^e*10^e = m1*m2*10^(e + e)

Damit man jetzt am ende wieder e als exponenten hat und nicht 2e müssen wir das nochmal auseinander ziehen:

Code: Alles auswählen

= (m1*m2*10^e)*10^e

Somit ist unsere mantisse für das produkt vom m1*m2 genau m1*m2*10^e
Angenommen e=-2 (also 2 nachkommastellen) dann ist 10^-2 = 0,01

Code: Alles auswählen

1,5*1,25 = 1,875 => 150*0,01 * 125*0,01 = 18750*0,01*0,01 =* 187,50*0,01 = 1,875


Eine fixpunktimplementierung könnte also so aussehen:

Code: Alles auswählen

function fpAdd(a, b: Integer);
begin
  Result := a + b;
end;
function fpMul(a, b: Integer);
begin
  Result := a * b div 100; // *0.01 = *e
end;


Viel effizienter geht es nicht, das ist entweder genau eine addition, oder eine multiplikation und eine division. Da ist nix was eine super schlaue bibliothek schneller machen könnte als der FPC

Das ist übrigens auch der Grund warum Dezimal Fließpunktarithmetik so eine schlechte Idee ist, während man bei fixpunktarithmetik nur additionen und multiplikationen hat, muss man bei fließpunktarithmetik darüber branchen auf welchen exponenten erweitert wird, das ist deutlich langsamer als eine berechnung die in einem, maximal 2 CPU cyclen durch ist. D.h. obwohl Fließpunktarithmetik natürlich genauer sein kann (nicht muss, wenn alle zahlen sich in einem bestimmten exponenten bereich aufhalten macht es keinen Unterschied), hat das doch massive Laufzeitauswirkungen

Lemmy
Beiträge: 57
Registriert: Do 23. Feb 2017, 06:18

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von Lemmy »

wp_xyz hat geschrieben:
Lemmy hat geschrieben:Laufzeit bei größeren Importen liegt bei 4-6h

Vielleicht bin ich naiv, weil ich nicht vom Fach bin, aber ich kann mir außer Rechnungen in der Quantenmechanik oder für Finite Element-Simuationen kaum etwas vorstellen, was so lang rechnet. Ich denke, da ist etwas anderes faul, und der Unterschied float/currency ist nebensächlich.


hab nie behauptet, dass die Berechnug 4-6 h dauert.

Eine Plattform habe ich zum Testen hier, da werden 38 MByte Daten importiert, die DB (ein Dump davon) ist 14 GByte groß ein Import läuft ca. 20 Minuten, davon fallen
* auf den Import ca. 3 Minuten
* auf die Nachverarbeitung ca. 2 Minuten
* auf das Zusammenführen von bestimmten Datensätzen ca. 7 Minuten
* auf die Berechnung um die es hier eigentlich geht ca. 9 Minuten.
...

Und beim letzen Punkt: Wenn ich hier Double mit Currency austausche dauert das ca. 20% mehr Zeit.

Lemmy
Beiträge: 57
Registriert: Do 23. Feb 2017, 06:18

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von Lemmy »

Warf hat geschrieben:Eine fixpunktimplementierung könnte also so aussehen:
....
Viel effizienter geht es nicht, das ist entweder genau eine addition, oder eine multiplikation und eine division. Da ist nix was eine super schlaue bibliothek schneller machen könnte als der FPC


naja, effizienter geht es dann, wenn man das DIV 100 nicht bei jedem Rechenschritt macht (wie currency), sondern nur einmal am Ende, wenn das Ergebnis wieder "raus" kommt.
Macht die Berechnung an sich natürlich nicht einfacher, und wenn ein Zwischenergebnis nochmal multipliziert werden müsste, kommen nochmal ein paar nullen oben drauf, dann müsste man am Ende noch wissen wie oft multipliziert wurde...

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von Winni »

Lemmy hat geschrieben:naja, effizienter geht es dann, wenn man das DIV 100 nicht bei jedem Rechenschritt macht (wie currency), sondern nur einmal am Ende, wenn das Ergebnis wieder "raus" kommt.
Macht die Berechnung an sich natürlich nicht einfacher, und wenn ein Zwischenergebnis nochmal multipliziert werden müsste, kommen nochmal ein paar nullen oben drauf, dann müsste man am Ende noch wissen wie oft multipliziert wurde...



Die Division durch 100 müssen sie schon machen, weil sie sonst immer die Mantisse mitführen müssen - das nennt man aber bekanntlich Fließkomma-Werte. Und das zweite Problem ist, falls viele Multiplikationen vorliegen, muss man auch darauf achten, ob man noch im möglichen Wertebereich liegt, wenn man da mit großen Werten arbeitet. Auch ein Int64 ist endlich.

Auf der anderen Seite gibt es bei dem div 100 ja jedesmal einen Rundungsfehler, der bei kurzen Berechnungen durch die dritte und vierte Stelle hinter dem Komma abgefedert wird, aber bei Kettenadditionen zu Abweichungen führen kann.

Alles in allem sehe ich nicht, wie Du die Berechnungen großartig beschleunigen kannst.

Zwei Fragen:

* Benutzt Du inline code für die Berechnungen?
* Ist das alles Single Thread oder beutzt Du mehrere?

Winni

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von m.fuchs »

Lemmy hat geschrieben:naja, effizienter geht es dann, wenn man das DIV 100 nicht bei jedem Rechenschritt macht (wie currency), sondern nur einmal am Ende, wenn das Ergebnis wieder "raus" kommt.
Macht die Berechnung an sich natürlich nicht einfacher, und wenn ein Zwischenergebnis nochmal multipliziert werden müsste, kommen nochmal ein paar nullen oben drauf, dann müsste man am Ende noch wissen wie oft multipliziert wurde...

Das hängt ja vom Anwendungsfall ab. Wenn es um finanztechnische Berechnungen geht hat man wenig Probleme. Man multipliziert ja selten zwei Preise mit einander sondern eine Anzahl mit einem Preis. Diese Anzahl wird also dann nicht als Fixpoint-Wert vorliegen.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von Winni »

Hi!

Na, der Ärger kann doch schon ,bei den Wechselkursen losgehen.
Heute gibt es für einen € 10376.- Guinea-Franc.
Und ich erinnere mich noch an Zeiten, wo der Taschenrechner einen overflow error hatte:
In den 80ern gabs für 1.- DM 15000.- polnische Zloty.

Winni

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von Warf »

Winni hat geschrieben:Hi!

Na, der Ärger kann doch schon ,bei den Wechselkursen losgehen.
Heute gibt es für einen € 10376.- Guinea-Franc.
Und ich erinnere mich noch an Zeiten, wo der Taschenrechner einen overflow error hatte:
In den 80ern gabs für 1.- DM 15000.- polnische Zloty.

Winni

Ja, bei Integer (also 32 bit) hat man 2 mrd relativ schnell voll. Und selbst 64 bit ist zwar groß, aber wenn spätestens nach 19 multiplikationen mit 10 ists auch schon voll. Da ich zwar davon ausgehe das man nicht so bald mit 10^15 (10^19 mantisse /10^4 nachkommastellen) rauskommt (egal von welcher währung), sollte das als endergebnis vollständig ausreichen, aber als zwischenergebnis kann das schnell erreicht werden, weshalb ich auf jeden fall in jedem schritt durch teilen würde.

Winni hat geschrieben:Auf der anderen Seite gibt es bei dem div 100 ja jedesmal einen Rundungsfehler, der bei kurzen Berechnungen durch die dritte und vierte Stelle hinter dem Komma abgefedert wird, aber bei Kettenadditionen zu Abweichungen führen kann.


Den kann man noch ein wenig beinflussen indem man die Division in Real ausführt (was mit einer 64bit mantisse ja die selbe präzision wie in64 hat, sogar mehr da int64 nur 63 bit effektiv hat wegen sign) und danach rundet.
Also etwa so:

Code: Alles auswählen

function fpMul(a, b: Int64): Int64;
begin
  Result := Round(Real(a) / Real(b));
end;

Round macht kaufmännisches runden, natürlich kann man auch andere rundungsverhalten benutzen (round to nearest even, ceil, trunc, etc.)
Das ist aber ein echter performance killer, und da kann man statdessen auch einfach die nachkommastellen um eins erweitern. Einen rundungsfehler hat man immer wenn man in den bereich kommt (z.B. bei Zinseszins), bzw generell wenn man die (unendlichen) Reelen Zahlen versucht mit endlichem Speicher darzustellen. Die art der darstellung bestimmt daher den Rundungsfehler. Bei dieser darstellung kann bei additionen kein rundungsfehler entstehen, genuso wenig wie beim multiplizieren mit Ganzzahlen, weshalb 4 nachkommastellen (wie sie currency hat) eigentlich ausreichend sein sollten.

Tatsächlich lassen sich integer multiplikationen auch ohne div darstellen (indem man statt intValue*10000 und danach div 10000 macht einfach nur intValue benutzt, also die nachkommazahlen weglässt) und bei additionen hat man auch lediglich die Integer addition. Das sind alles sachen die der FPC automatisch machen kann, daher denke ich kann man ziemlich sicher sagen, zumindest auf dieser ebene, kann man performancemäßig nix mehr rausholen, und ist in diesen fällen (integer multiplikation und addition) sogar so schnell wie nur möglich (wahrscheinlich sogar schneller als double), und nur bei der Fixpunkt multiplikation kommt overhead dazu

Da bleiben also nur 3 möglichkeiten, Algorithmische verbesserungen (Asymptotische laufzeit), Optimierungen (speicherzugriff, loop unrolling, etc, eventuell auf compiler ebene oder per hand), oder parallelisierung.
Alles 3 braucht recht große eingriffe in den bestehenden Code (algo, parallelisieren, händisches optimieren)/Das projekt (kompiler optimierungen).

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von Winni »

Hi!


Hab ich doch gesagt.
Parallelisieren und inline code.

Real ist komplett veraltet und hatte seinerzeit 48 Bit.
Nun wird es nur noch aus sentimentalen Gründen und Abärtskompatitbilität mitgeschleppt.
Kann sein, dass es irgendwann mal aus fpc rausgeschmissen wird.

Winni

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von Warf »

Winni hat geschrieben:Real ist komplett veraltet und hatte seinerzeit 48 Bit.
Nun wird es nur noch aus sentimentalen Gründen und Abärtskompatitbilität mitgeschleppt.
Kann sein, dass es irgendwann mal aus fpc rausgeschmissen wird.


Stimmt, ich meinte natürlich Extended und nicht Real

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Fixpoint - library bzw. sinnvolles Vorgehen

Beitrag von Winni »

Hi!

Vorsicht mit extended auf 64 Bit Maschinen! Sie sind dort nix anderes als eine alias für Double.

Hintergrund ist, dass die 32 Bit Processoren mit extended als 80 Biter umgehen können, die 64 Bit Procs von AMD und Intel aber nicht.
Für Details frag bitte die Assembler Fraktion - dazu gehöre ich nicht.

Winni

Antworten