Frage

Ich habe eine Methode, die sich mit einigen geographischen Koordinaten in .NET, und ich habe eine Struktur, dass ein Paar speichert so koordinieren, dass, wenn 256 in für eine der Koordinaten übergeben wird, wird es 0 jedoch in einer bestimmten Instanz ein Wert von etwa 255.99999998 berechnet wird, und somit in der Struktur gespeichert. Wenn es in ToString () gedruckt ist, wird es 256, was nicht passieren sollte - 256 0 sein soll ich habe nichts dagegen, wenn es 255,9999998 gedruckt, aber die Tatsache, dass es druckt 256, wenn der Debugger zeigt 255,99999998 ein Problem ist. Mit besser ist es sowohl speichern und anzeigen 0 wäre sogar.

Im Einzelnen gibt es ein Problem mit Vergleich. 255.99999998 ausreichend nahe an 256, so dass er es sollte gleich. Was soll ich tun, wenn verdoppelt Vergleich? verwenden irgendeine Art von Epsilon-Wert?


EDIT:. Genauer gesagt, mein Problem ist, dass ich einen Wert annehmen, führe einige Berechnungen, dann die entgegengesetzten Berechnungen auf dieser Nummer durchführen, und ich brauche genau den ursprünglichen Wert zurück

War es hilfreich?

Lösung

Sie könnten den epsilon Ansatz verwenden, aber das Epsilon ist in der Regel ein Fudge, die Tatsache zu umgehen, dass Gleitkomma-Arithmetik verlustbehafteten ist.

Das könnten Sie betrachten Floating-Punkte ganz zu vermeiden binären und eine schöne Rational-Klasse verwenden.

Die Berechnung oben wahrscheinlich dazu bestimmt 256 sein, wenn Sie lossless Arithmetik zu tun wurden, wie Sie mit einem Rational-Typ erhalten würden.

Rational-Typen mit Namen Ratio oder Fraction-Klasse und sind ziemlich einfach zu schreiben gehen

Hier ist ein Beispiel . Hier anderen


Bearbeiten ....

Um zu verstehen, Ihr Problem zu berücksichtigen, dass, wenn der Dezimalwert 0,01 in eine binäre Darstellung umgesetzt wird, kann es nicht genau in endlichen Speicher abgelegt werden. Die Hexidecimal Darstellung für diesen Wert ist 0.028F5C28F5C wo die „28F5C“ unendlich wiederholt. Also noch bevor irgendwelche Berechnungen zu tun, verlieren Sie Exaktheit nur um 0,01 im Binärformat zu speichern.

Rational und Dezimal-Klassen werden verwendet, um dieses Problem zu überwinden, wenn auch mit einem Leistungskosten. Rational Typen vermeiden dieses Problem, indem einen Zähler zu speichern und einen Nenner Ihren Wert darzustellen. Decimal-Typ verwenden eine binärcodierte dezimale Format , die verlustbehafteten in Teilung sein kann, kann aber speichern gemeinsame Dezimalwerte genau.

Für Ihren Zweck schlage ich vor, noch einen Rational-Typen.

Andere Tipps

Das klingt wie ein Problem mit, wie die Zahl gedruckt wird, nicht, wie sie gespeichert wird. Ein double hat etwa 15 signifikante Zahlen, so ist es 255,99999998 von 256 mit Präzision zu Ersatz sagen kann.

Sie können Formatstrings wählen, lassen sollten Sie so viel von der Zahl angezeigt werden, wie Sie möchten.

Die übliche Art und Weise verdoppelt auf Gleichheit zu vergleichen ist, sie zu subtrahieren und sehen, ob der Absolutwert kleiner als ein vordefinierter epsilon, vielleicht 0,000001.

Sie haben sich auf einer Schwelle, um zu entscheiden, unter denen zwei Werte gleich sind. Diese Mengen zur Verwendung von sogenannten Festpunktzahlen (im Gegensatz zu Gleitkomma Gegensatz). Dann müssen Sie manuell die Aufrundung auszuführen.

Ich würde mit bekannter Größe mit einem gewissen Typ ohne Vorzeichen gehen (zB. Uint32 oder uint64, wenn sie verfügbar sind, ich weiß nicht .NET) und behandeln es als Festpunktzahl Typ mod 256.

Eg.

typedef uint32 fixed;

inline fixed to_fixed(double d)
{
    return (fixed)(fmod(d, 256.) * (double)(1 << 24))
}

inline double to_double(fixed f)
{
    return (double)f / (double)(1 << 24);
}

oder etwas ausgefeilteren eine Rundungskonvention entsprechen (zum nächsten, zu senken, was zu höheren, auf ungerade, sogar). Die höchsten 8-Bits von festen Halt der ganzzahlige Teil, die 24 unteren Bits den Bruchteil halten. Absolute Genauigkeit ist 2 ^ {- 24}

.

Beachten Sie, dass das Hinzufügen und Substraktion solche Zahlen natürlich umschlingt bei 256. Bei der Multiplikation, sollten Sie aufpassen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top