Intern mit Mantisse Exponent rechnen



  • Hi zusammen

    ich habe mal gelesen, dass man, wenn man intern viel mit Kommazahlen rechnet, auch auf eine Mantisse Exponent Basis wechseln kann, um dann nur noch mit ganzen Zahlen zu rechnen. Hat das schonmal jemand gemacht? Auf welcher Basis wird dann gerechnet? Arbeitet man dann mit der 2^e * m Representation oder eher mit einer Basis von 10?

    Denkbar wäre ja auch, dass man sich auf einen fixen Exponenten für das ganze System festlegt bei einer Basis von 10 z.b. 6 NKS und dann entsprechende jede Zahl nur noch als Mantisse repräsentiert.

    Das Netz ist zu dem Thema nicht besonders ertragreich, außer dass man rausfinden kann, wie man Gleitkommazahlen in Mantisse und Exponent aufspaltet.

    Welche Vorteile ( abgesehen davon, dass man nur noch mit ganzen Zahlen rechnen muss ), hat das dann?

    Gibts Erfahrungen?


  • Mod

    Nicht wirklich gemacht, aber in Betracht gezogen. Und dann nicht gemacht.

    Zuerst einmal die primären Gründe, warum oder warum nicht:

    • Pro: Du kannst eventuell Geschwindigkeit gewinnen
    • Contra: du verlierst die Möglichkeit, Zahlen aus verschiedenen Wertebereichen zusammen zu verarbeiten. Das ist eine ziemlich wesentliche Einschränkung.

    Weitere zufällige Gedanken dazu:

    • Die Wahl der Basis sollte recht egal sein, da du den Exponenten ja nicht (bzw. höchstens einmal) speichern brauchst.
      • Mit Basis 2 (oder anderen Zweierpotenzen) ist die Umrechnung in einem binären Rechenwerk halt besonders effizient, weil's ein schneller Bitshift ist, anstatt Multiplikation/Division.
      • Übliche Hardwarerechenwerke für Fließkommazahlen nehmen daher auch die 2 als Basis, aber das sollte kein starker Grund zum Nachmachen sein, weil die andere Anforderungen haben. Aber zumindest es ist zumindest ein Präzedenzfall aus einem ähnlichen Problem, wo die Welt der Meinung ist, 2 wäre optimal.
      • Für manche Spezialanforderungen werden auch andere Basen genommen. Man hört oft, in der Finanzmathematik würde 10 benutzt werden. Ich weiß nicht, ob das rechtliche Gründe hat, ob Finanzler nicht genug Ahnung von Mathe haben, oder beides. ich weiß auch nicht, ob das überhaupt stimmt.
      • Mit kleinen Basen hast du mehr Feinkontrolle über den wählbaren Bereich, und selbst mit der minimalen Basis von 2 kommt man recht weit, ohne große Exponenten. Aber letztlich halt egal, da dein Basis-Exponenten-Paar ja ohnehin fix (oder nahezu fix) sein wird.
      • Prinzipiell braucht du ja nicht einmal eine Basis und Exponent, sondern kannst beliebig krumme Faktoren nehmen.
    • Hardware für Fließkommaberechnung ist sehr optimiert. Du darfst bei deiner Integerrechnung keine Performance verschenken und musst alle Tricks anwenden, sonst bringt es nix.
      • Die Hardware für Integer ist natürlich auch entsprechend optimiert, also ist durchaus Potential da
    • Mach das nur, wenn du wirklich die allerletzte Performance brauchst, oder es dich brennend interessiert! Es gibt viel niedriger hängende Früchte bei der Optimierung, die erst abgepflückt werden sollten.


  • @SeppJ sagte in Intern mit Mantisse Exonent rechnen:

    Für manche Spezialanforderungen werden auch andere Basen genommen. Man hört oft, in der Finanzmathematik würde 10 benutzt werden. Ich weiß nicht, ob das rechtliche Gründe hat, ob Finanzler nicht genug Ahnung von Mathe haben, oder beides. ich weiß auch nicht, ob das überhaupt stimmt.

    Es gibt häufig Vorschriften, mit exakt n Nachkommastellen zu rechnen. (n \in [2, 4, 0]). Wenn du Zinsen und Zinseszinz berechnen willst, ist das relevant. Bestimmt auch in anderen Bereichen. Bin kein Finanzmathematiker.



  • Zunächst mal ein großes Danke für eure Ausführungen. Ich finde das Thema interessant und habe gerade ein Projekt, bei dem ich allerlei an Innovation unterbringen kann. Daher forsche ich in verschiedenste Richtungen. Ob dies hier es in das Projekt schafft, ist offen.

    Ich hatte ein wenig rumgespielt mit dieser Zahlenrepräsentation und festgestellt dass sich damit irgendwie nicht so richtig komfortabel rechnen lässt.

    Ich habe folgendes gemacht:

    • den Double auseinandergebaut. Aufgesplittet in Sign ( bool ), Exponent (int16_t) und Mantissa (int64_t). Und eben die entgegengesetze Operation. Soweit alles gut.
    • dann dachte ich, wenn die Exponenten und die Vorzeichen gleich sind, müsste man ja eine Addition als Mantisse1 + Mantisse2 abbilden können. Da kam dann aber totaler Quark raus. Vermutlich darf man die Mantissa im Double nicht einfach als ganze Zahl verstehen. Oder aber ich habe das erste Bit der Mantissa was immer 1 ist, falsch behandelt.
      ODer eben ein Denkfehler.

  • Mod

    Klingt von der Beschreibung her erst einmal richtig, müsste man im Detail prüfen, was du da genau falsch gemacht hast.



  • Nächster Gedanke war:

    • wenn sich die Exponenten unterscheiden shiftet man einfach die Mantisse mit dem größeren Exponenten nach links bis die Exponenten gleich sind und kann dann die Operation vornehmen.


  • @It0101 sagte in Intern mit Mantisse Exponent rechnen:

    wenn sich die Exponenten unterscheiden shiftet man einfach die Mantisse mit dem größeren Exponenten nach links bis die Exponenten gleich sind und kann dann die Operation vornehmen.

    Nehmen wir mal an, du möchtest 12345 * 10^100 + 678 * 10^0 rechnen. Wenn du dann 12345 100x nach links shiftest, ist nichts mehr drin... (so viele Bits hast du nicht). Du bekommst also das falsche raus. Du solltest in diesem Falle also umgekehrt vorgehen.



  • Stimmt. Diesen Sonderfall muss ich berücksichtigen.



  • @SeppJ sagte in Intern mit Mantisse Exonent rechnen:

    • Für manche Spezialanforderungen werden auch andere Basen genommen. Man hört oft, in der Finanzmathematik würde 10 benutzt werden. Ich weiß nicht, ob das rechtliche Gründe hat, ob Finanzler nicht genug Ahnung von Mathe haben, oder beides. ich weiß auch nicht, ob das überhaupt stimmt.

    Das hat rechtliche Gründe, da Rechnungen zur Basis 2 andere Ergebnisse z.B. bei der Zinsberechnung ergeben. Konten müssen aber exakt so geführt werden, wie man sie von Hand berechnen würde. Daher muss man das Zehnersystem nutzen. IBM hat bei den neueren POWER CPUs und den z/OS Systemen CPUs verbaut die in Hardware mit dem Zehnersystem rechnen können, und meines Wissen wird dafür kein BCD genutzt wie etwa früher bei den 68k CPUs.



  • @SeppJ sagte in Intern mit Mantisse Exponent rechnen:

    • Pro: Du kannst eventuell Geschwindigkeit gewinnen

    Ein weiteres Pro ist, dass sich die berechnungsergebnisse damit leichter auch über Architektur- und Compilergrenzen hinweg absolut exakt reproduzierbar machen lassen.

    Ein Beispiel, wo so etwas nützlich sein kann, sind Netzwerkspiele, die den gemeinsamen Zustand des Spiels via Lockstep synchronisieren. Hier werden sehr effizient ausschliesslich die Usereingaben zwischen den Clients ausgetauscht, die dann den gemeinsamen Zustand jeder für sich berechnen und natürlich alle zum selben Ergebnis kommen müssen.


  • Mod

    @It0101 sagte in Intern mit Mantisse Exponent rechnen:

    Nächster Gedanke war:

    • wenn sich die Exponenten unterscheiden shiftet man einfach die Mantisse mit dem größeren Exponenten nach links bis die Exponenten gleich sind und kann dann die Operation vornehmen.

    Moment. Wenn du anfängst, Mantissen zu shiften, dann programmierst du eine Software-Emulation für Floating-Point-Zahlen. Das ist garantiert viel langsamer als die Hardwareroutinen (Es gab früher Zeiten, wo das ein wesentliches Verkaufsargument für Prozessoren war, wenn er entsprechende Hardware hatte, weil das so ungemein schneller war…). Der Trick mit den Integers funktioniert nur, wenn alle Zahlen ungefähr dir gleiche Größenordnung haben. Dann kannst du Geschwindigkeit gewinnen, weil du die Komplexität von Floating-Point-Zahlen eigentlich gar nicht voll ausschöpfst, und daher mit Tricks die Berechnungen in einfachere (und schnellere) Ganzzahlrechnungen umformulieren kannst.



  • Hallo @It0101

    Nochmal zum Addieren der Mantissen. Im Double-Format hast Du eine 52 Bit Mantisse. Ich versuchs mal mit einem 4 Bit -Beispiel:
    1010
    1100
    Das musst Du binär als
    1.1010
    1.1100
    interpretieren. Die 1 vor dem Komma wird nicht mitgespeichert, da es im Binärfomat immer eine 1 ist. Das kannst Du jetzt addieren zu:
    11.0110
    Das kannst Du natürlich nicht so als Mantisse in den Double zurückschreiben, den vor dem Komma steht jetzt 11 und per Definition muss da immer 1 stehen. Das heißt, Du musst die Manitisse um 1 Bit nach rechts schieben und zum Expont eine 1 addieren um die korrekte Double Darstellung zu erhalten:
    11.0110 >> 1
    = 1.1011
    Die 1 vor dem Komma wird nicht mitgespeichert, also bleibt
    1011
    als Mantisse übrig.
    Wenn Du das verstanden hast, braucht Du den Teil mit "1." davorschreiben und beim Ergebnis wieder wegnehmen nicht mehr, Addition und Shift funktioniert auch ohne.



  • Vielen Dank für eure rege Diskussion und Unterstützung. Den Fehler beim Addieren habe ich jetzt auch verstanden. 🙂

    @SeppJ Ich hatte schon befürchtet dass man bei dem Thema sehr leicht Performance verschenkt und dann letztendlich wieder langsamer ist als der Prozessor wenn er mit Doubles rechnet.

    Da ich tatsächlich in der Finanzwelt unterwegs bin, wäre prinzipiell auch eine Basis von 10 zielführender. Und da ist dann die Konvertierung eines Doubles ( die von Außen ins System reinkommen ) wieder aufwändiger.


  • Mod

    Ich hoffe doch, dass selbst im modernen Finanzwesen ein 64 Bit Integer ausreichend ist, alle vorkommenden Beträge mit großzügig vielen Nachkommastellen auch ohne Exponentialschreibweise darzustellen.



  • Für die meisten normalen Dinge wird es reichen.
    Allerdings...

    MS verwendet für Geld Fixkomma mit Faktor 10000* (auf die Hauptwärhung bezogen, also ein Euro = 10000, ein Cent = 100). Bin mir aber nicht sicher ob das für alle Zwischenergebnisse ausreichend ist. Aber gehen wir mal davon aus dass es reicht.

    2^64 / 10000 = 1.8446744e+15
    Das "global gross domestic product" 2019 war 142 "trillion" (wie es die Amis verwenden also 1 trillion = 10^12), also 1.42e+14.

    IMO kann das schnell eng werden. Sowieso wenn man irgendwelche Rechnungen zur Weltwirtschaft macht und diese "unskaliert" machen möchte und da ein bisschen Daten über mehrere Jahre akkumuliert. Möglicherweise sogar wenn es "nur" um Firmen geht die Billionenbeträge in ihrer internen Buchhaltung zigfach im Kreis rum schieben und man irgendwo die Summe aller Ein- oder Ausgänge berechnen muss. Oder richtig fette Day-Trading Sachen + ebenfalls die Summe aller Käufe oder Verkäufe über z.B. ein Jahr. Ich kenne mich in dem Sektor aber zu wenig aus. Mag sein dass ich mich täusche und das unrealistische Annahmen sind 🙂

    *: Damit meine ich den COM-Standard "Currency" Datentyp und SQL Servers "money" Datentyp. Das heisst natürlich nicht dass alle MS Anwendungen damit arbeiten. Wenn es irgendwas für Buchhaltung von MS gibt, ist davon auszugehen dass die mit der passenden Anzahl Nachkommastellen rechnen die für die jeweilige Legislatur passend ist.



  • Also für mein Projekt hätte ich jetzt 4 NKS ( also 10000 ) als Grundlage genommen und für das saubere Berechnen von Zwischenergebnissen und um die Rundungsfehler nicht zu groß werden zu lassen, nochmal 2 dazu genommen also mit 6 NKS gerechnet. Damit ist man zumindest im Börsenumfeld sauber. Würde ich Zinsberechnung machen hätte ich vielleicht noch mehr genommen.



  • @It0101 sagte in Intern mit Mantisse Exponent rechnen:

    Also für mein Projekt hätte ich jetzt 4 NKS ( also 10000 ) als Grundlage genommen und für das saubere Berechnen von Zwischenergebnissen und um die Rundungsfehler nicht zu groß werden zu lassen, nochmal 2 dazu genommen also mit 6 NKS gerechnet. Damit ist man zumindest im Börsenumfeld sauber. Würde ich Zinsberechnung machen hätte ich vielleicht noch mehr genommen.

    Aber warum? Sind die Preise so genau? Wie bezahlst du 42,123456 Euro an jemanden? Der Punkt ist ja auch, dass man manchmal gezwungen ist zu runden, weil es bestimmte Summen in der Realität gar nicht gibt.



  • @wob
    Wenn du Dinge rechnest die in der Buchhaltung eines Unternehmen landen, dann gibt es genaue Vorschriften wo mit wie viel Genauigkeit zu rechnen ist, wo und wie genau gerundet werden muss etc. Da ist an vielen Stellen sub-Cent Genauigkeit vorgeschrieben.

    Also Beispielsweise wenn du 100 Artikel um 1 Cent verkaufst, dann musst du ja Steuer zahlen. Wenn du jetzt 100 mal die Steuer für 1 Cent berechnest und das aufaddierst, brauchst du mehr Genauigkeit als nur 1 Cent damit da was vernünftiges rauskommt.

    Ähnliche Fälle kann es auch geben wenn man bloss intern rumrechnet, ohne gesetzliche Auflagen.

    Wie bezahlst du 42,123456 Euro an jemanden?

    Wie bezahl ich 0,891 Euro an jemanden? Trotzdem werden Spritpreise mit 3 NKS angegeben und gerechnet. Für den finalen Preis wird dann auf 2 NKS gerundet. Aber wenn du 10 Liter kaufst zahlst du eben 8,91 Euro und nicht 8,90.


Log in to reply