Flexible Klasse fuer reelle Zahlen?
-
Wie könnte man eine Klasse so entwerfen, sodass man möglichst 'verlustfrei' mit reellen Zahlen rechnen kann?
D.h. bei komplexeren Berechnungen tritt ja oft der Fall ein, dass sich z.B. eine Quadratwurzel 'kürzen' lässt und das Ergebnis dann wieder rational ist. Wenn ich mich auf double beschränke, und z.B. eine Quadratwurzel immer sofort ausrechne, dann fällt es mitunter (aufgrund Genauigkeitsverlusten) gar nicht auf, dass sowohl im Zähler als auch im Nenner ein ganzzahliges Vielfaches der selben Quadratwurzel steht, und (im aktuellen Fall versuche ich z.B. die Cardano-Formeln für kubische Gleichungen zu programmieren) es kommt am Ende z.B. für x als Lösung 3.0000256 heraus, obwohl eigentlich genau 3 herauskommen sollte.
Ich hätte an so etwas ähnliches gedacht:class Bruch{ long Zaehler; long Nenner; }; class reelle_Zahl{ long Zaehler; /* Falls die Wurzeln im Radikand und im Exponenten ueber- einstimmen, haette bei sqrt(2) + sqrt(2) der Zaehler z.B. den Wert 2 */ Bruch Radikand; Bruch Exponent; };aber das greift leider auch irgendwie zu kurz. Wahrscheinlich bräuchte es eine etwas kompliziertere Datenstruktur dazu (?)
Wenn jemandem eine Idee dazu einfaellt: Es spielt keine Rolle, ob das Klassenkonstrukt dann unbequem zu handhaben oder laufzeittechnisch oder sonstwie nicht optimal ist! Einzig wichtig wäre, dass man damit einigermaßen verlustfrei in R rechnen kann. Oder womöglich gibt's ja auch irgendwo eine Bibliothek dazu.
Besten Dank für Anregungen und Ratschläge!
-
Möglichst verlustfrei kann man in der Menge R meiner Meinung nach lediglich mit Symbolen rechnen - die Menge der irrationalen Zahlen macht einem das Leben ja nicht gerade einfacher.
Wenn "echte" Werte hinzu kommen, dann hängt das schlussendlich von der gewählten/verfügbaren Genauigkeit des Datentyps ab. Da die Genauigkeit immer begrenzt ist, ist ein erwartet exaktes Ergebnis eher eine Randerscheinung.
Die beste Möglichkeit wird sein, die Zahl der Berechnungen möglichst gering zu halten, damit sich die Ungenauigkeiten nicht aufmultiplizieren.
Des weiteren sollte man sich von dem Gedanken verabschieden, exakte Ergebnisse "nieder schreiben" zu können, wenn man in der Menge R rechnet.
Grüße... Heiko
-
Nimm doch eine 64 Bit Zahl und setze das Komma zum Beispiel an der 6. Stelle fest. Und dann rechnest du entsprechend. So ist die Zahl immer auf 6 Nachkommastellen genau, der Rest wird abgeschnitten. Bei einer 64 Bit Zahl mit 6 Nachkommastellen kann die Zahl trotzdem noch eine Grösse von +- 9 Billionen erreichen.
Beim rechnen einfach mit der 64 Bit Zahl rechnen und bei der Multiplikation bzw. Division die Anpassung nicht vergessen.
Bsp:
class CCurrency { // Static attributes // public: static int const DECIMALS_COUNT = 6; static int const DECIMAL_ADJUSTEMENT = 1000000; // Attributes // private: long long m_llValue; // Sofern dein Kompiler long long unterstützt, ansonsten eine andere 64 Bit Zahl. // Constructors & Destructor // public: CCurrency(int iValue, unsigned int iDecimalValue) : m_llValue(iValue * DECIMAL_ADJUSTEMENT + iDecimalValue) {} CCurrency() : m_llValue(0) {}; ~CCurrency() { }; // Operators // public: CCurrency& operator =(CCurrency const& rCurrency) { m_llValue = rCurrency.m_llValue; return *this; } CCurrency& operator +=(CCurrency const& rCurrency) { m_llValue += rCurrency.m_llValue; return *this; } // usw. };Du kannst natürlich die Kommastellen noch verschieben. Könntest auch templates dazu verwenden und die Sache sehr dynamisch machen.
Falls du wirklich absolut genaue Zahlen haben willst. Also überhaupt nichts abgeschnitten, dann musst du wohl symbolisch rechnen.
Ich hoffe das hilft dir weiter.Grüssli
-
Ich bezweifle ehrlich gesagt, dass so etwas sinnvoll geht. Selbst rationale Zahlen haben ja teilweise eine nicht endliche Dezimal- bzw. Dualentwicklung. Du müsstest dafür im Prinzip deine Rechnungen komplett algebraisch durchführen (da lässt sich sicherlich mit Expression Templates was lustiges (aber auch ganz schön abgefahrenes) und faules basteln), was dann erst bei der Auswertung (== Umwandlung nach double) den Term möglichst genau ausrechnet.
BTW, wenn es dir nur um das Lösen kubischer Gleichungen geht, die Ergebnisse bekommt man wohl mit dem Newtonverfahren genauer raus.
/edit: Jetzt wo ich's mir überlege find ich's ganz schön interessant. Mal sehen, ob sich da was machen lässt.