2 Stimmen

Zero-Rounding-Error-Klasse in .Net?

Hallo, ich frage mich, gibt es eine Klasse in .Net, die verwendet wird, um genaue Zahlen ohne Rundungsfehler zu berechnen?

Das ist zum Beispiel nicht das, was ich will:

decimal dividend = Decimal.One;
decimal divisor = 3;
dividend/divisor * divisor // gives us 0.9999999999999999999999999999 instead of 1

Ich habe mir überlegt, ob es eine Zahlenklasse gibt, die Puffer bis zu dem Zeitpunkt, an dem wir sie anzeigen müssen, mit anderen Worten, es würde wie folgt aussehen:

Num n = new Num(1);
n.DivideBy(3);
n.MultiplyBy(3);
n.toString(); // gives us "1"

Num n2 = new Num(n);
n2.DivideBy(3);
int decimal_places = 8;
n2.RoundHalfUp(decimal_places);
n2.toString(); // gives us "0.33333333"

Natürlich ist dies nur ein Beispiel für eine Implementierung. Im Grunde geht es hier darum, dass ich eine Klasse suche, die keine Rundungsfehler aufweist (normalerweise durch Verzögerung der Berechnungen bis zum letzten Moment).

Ich verstehe, dass die Leistung langsamer sein würde als Double ou Decimal . Aber sie muss nicht blindlings Berechnungen anstellen, solange sie sich innerhalb akzeptabel Zeit.

7voto

Alexandre C. Punkte 53706

Dies ist ein Job für rationale Zahlen . Wenn Sie nur arithmetische Operationen (einschließlich Division) durchführen, brauchen Sie nichts zu verzögern.

Wenn Sie beliebige kontinuierliche Funktionen (z. B. Logarithmen, Kosinus, Quadratwurzeln usw.) berechnen müssen, wird daraus Weg mehr beteiligt. Die benötigten Ziffern zur Gewährleistung der geforderten Genauigkeit im Auge zu behalten, ist schwierig, aber durchaus machbar, wenn auch in der Praxis ineffizient. Die Idee ist, neben jeder Funktion eine weitere Funktion zu speichern, die eine Kontinuitätsmodul (Sie erhalten das, was man als " intuitionistisch kontinuierliche Funktionen").

Beachten Sie, dass das Speichern eines Ausdrucksbaums die Sache nicht sehr vereinfacht, da Sie den resultierenden (hoffentlich einfacheren) Ausdruck auswerten müssen.

Ein anderer Ansatz wäre, eine Potenzreihe zusammen mit einem Konvergenzradius zu speichern und bei Bedarf die Summe der Reihe zu berechnen.

1voto

svick Punkte 224493

Ihr spezielles Problem könnte durch einen Typ gelöst werden, der jeden Bruch exakt darstellen kann. Sie können dafür eine Bibliothek verwenden oder selbst eine schreiben (das sollte nicht so schwer sein).

Wenn Sie aber das allgemeine Problem lösen wollen, so dass Math.Pow(Math.Sqrt(2), 2) == 2 gibt zurück. true und das für beliebige Operationen funktioniert, bräuchte man einen Typ, der jede beliebige Berechnung darstellen kann und in der Lage ist, sie zuverlässig zu vereinfachen. Die Berechnung einfach nur zu verzögern, reicht nicht aus.

Ich bin mir nicht sicher, ob es so etwas gibt oder ob es überhaupt möglich ist.

0voto

dsolimano Punkte 8542

Vielleicht eine Bibliothek für Ganzzahlen beliebiger Genauigkeit für Ihre Bedürfnisse ausreichen würde?

Die verlinkte Antwort befasst sich mit C#, aber natürlich sind es wirklich allgemeine .NET-Antworten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X