C++ wie kann man bei einem float die Nachkommastellen als Ganzzahl speichern?

8 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Bevor man mit dem Programmieren beginnt, müssen erst Fakten klar sein:

§1: Quelle der Daten:

a) Bruch wie 11111/109 ist nicht einfach eine Zahl mit 14 oder 15 Nachkommastellen, sondern unendlich viele mit einer Periode 108 Ziffern

101.93577981651376146788990825688073394495412844...

b) Quelle ist eine Variable vom Typ Double dann sollte man es auch als Double {Array} speichern. Später hat man dann alle Freiheiten des Abschneidens usw.

§2: was darf verloren gehen? Verlustbehaftete Komprimierung erlaubt?

(also interessieren Dich immer nur 15 Ziffern)

c) Was ist mit Vorkommastellen?

§3: Priorität: Geschwindigkeit oder Speicherplatz sowohl beim Speichern (Einpacken) als auch beim Laden (Auspacken) 

§4: soll es leicht verständlich & flexibel sein? Dann sind Strings ideal:

- leicht lesbar & leicht zu Debuggen

- leicht speicherbar

- mit jedem Editor anzeigbar

Aber langsam und verbraucht viel Speicher.

Beispiel:

Wenn man 0 Verluste haben will, hohe Komprimierung (besonders bei irrationalen Zahlen) und höchste Geschwindigkeit an beliebiger Stelle (auch ab Position 1 Mrd. dann x Stellen)...

nehme ich das vom Weltmeister der Pi-Berechnung verwendete Format ycd.

Das ist vorn ein Header (Info, was ab wann wie verschlüsselt ist; kann aber auch entfallen, wenn man nur immer das selbe Format verwendet) und dahinter ein Array aus 64 Bit uint. Falls Deine Quelle Brüche sind, kann z.B. immer Zähler und dann Nenner gespeichert werden.

In uint64 kann man ein Block aus 19 Ziffern sehr schnell speichern und später auch sehr schnell auspacken, ohne die Mio. Stellen davor beachten zu müssen (was bei reiner Umwandlung sehr großer Zahlen in das HEX-Format tun müsste).

Die Komprimierungsrate liegt bei irrationalen Zahlen wie Pi konst. bei etwa 42% {100% wäre eine reine txt mit den Ziffern} und ist damit immer besser als ZIP, RAR usw.

Für die über 22 TB an Daten ist dieses Format in jeglicher Hinsicht unschlagbar.

Nachteil: für Anfänger etwas schwer verständlich und der HEX-Code ist wie bei jedem komprimierten Datei für normale Editoren nichtssagend ("Brei von Bytes").

  Du brauchst eine Funktion, die die Zahl ( 17/19 ) in eine Stringvariable schreibt ( z.B. Code in Fortran ) Dann suchst du das Komma mittels der Indexfunktion, die bestimmt in sämtlichen Programmiersprachen existiert.

katersaid11 
Fragesteller
 24.07.2017, 15:38

Ja hab das mittlerweile auch schon herausgefunden aber danke ^^ 

0

Falls die Vorschläge noch nicht genügen kannst du sicher auch einfach die benötigten bits aus der Variable auslesen. Ceevee hat deren Format ja bereits angegeben.

Dann brauchst du keinen Code von anderen und kannst mit dem float rechnen, den du schon hast. Ist trotzdem eher nicht so fancy...

Zur Not kannst du auch schriftlich Dividieren. ;)

Ich würde für den Anwendungsfall wahrscheinlich nicht double oder float nehmen - die Datentypen bringen aufgrund der Art, wie sie Zahlen speichern, Ungenauigkeiten und Rundungsfehler mit sich. 

Stattdessen würde ich eine Library dafür installieren, z.B.

https://gmplib.org/

und die bringt sicherlich auch ihre eigene String-Funktion mit. Ich bin in C++ nicht so sattelfest, ich weiß nicht, ob GMP dafür die beste Wahl ist.

katersaid11 
Fragesteller
 24.07.2017, 15:50

Naja. Ich versuche eigentlich sogut wie Möglich alle "fremde" Bibliotheken zu meiden. Irgendwie wurden diese schließlich auch gemacht -> heißt ich müsste das mit lernen auch selber machen können.

0
ceevee  24.07.2017, 16:09
@katersaid11

Du kannst das auch selber machen. Das halte ich aber für unnötig aufwändig, wozu das Rad ständig neu erfinden? 

Die Art und Weise, wie Programmiersprachen Fließkommazahlen abspeichern, ist in diesem Standard abgespeichert. 

https://de.wikipedia.org/wiki/IEEE_754

Deswegen ergibt z.B. 0.1 + 0.2 in der Programmierung nicht 0.3, sondern 0.30000000000000004.

Du müsstest dir ein eigenes Zahlenformat (für den Anfang wahrscheinlich stringbasiert) überlegen und darauf all die Rechenregeln anwenden. Sprich: die vier Grundrechenarten schriftlich untereinander ausführen, so wie du es in der Grundschule gelernt hast. In deinem Fall müsstest du das hier

http://www.frustfrei-lernen.de/mathematik/rechnen-kommazahlen-addieren-subtrahieren-multiplizieren-dividieren-mathematik.html

in Code pressen. Ein guter Programmierer macht nicht alles selbst, sondern weiß auch, wann "selbst machen" aufwandsmäßig in keinem Verhältnis mehr steht. 

0
katersaid11 
Fragesteller
 24.07.2017, 16:16
@ceevee

Ich hab schonmal einen String Taschenrechner mithilfe von int gemacht welches nur mit positiven und Ganzzahlen rechnen kann. Ich würde mich aber auch nicht als Programmierer bezeichnen von daher ist das schon ok ^^

0

Du multiplizierst deine Zahl mit 10^x, (wobei x die Anzahl der Nachkommastellen ist, die du haben willst) und parst das dann in einen int, wobei die restlichen Nachkommastellen abgetrennt werden.

katersaid11 
Fragesteller
 24.07.2017, 15:15

Ja das ist das Problem. Ich will halt alle bzw. soviele Nachkommastellen wie möglich haben.

0
Plokapier  24.07.2017, 15:23
@katersaid11

Wozu das?

Und außerdem ist dir schon klar, dass 1/19 eine periodische Zahl ist?

0
katersaid11 
Fragesteller
 24.07.2017, 15:28
@Plokapier

Es halt eigentlich keinen richtigen Grund :3

17/19

hab daran eigentlich nicht wirklich gedacht :/

0
Plokapier  24.07.2017, 15:35
@katersaid11

Ziemlich unnötig, wenn du mich fragst. Außerdem sind floating-points gar nicht in der Lage unendlich genau zu messen, die Unschärfe variiert (je nachdem, ob 32 oder 64 bit). Wenn du dich so sehr dafür interessierst, dann schau dir doch einfach mal den IEEE-Standard für floating-points an.

1