Frage

Als ich mit Programmieren angefangen meine erste app, die ich verwendet NSNumber für Geld Werte ohne zweimal zu denken.Dann dachte ich, dass vielleicht c-Typen waren genug, um deal mit meine Werte.Doch mir wurde geraten in der iPhone-SDK-forum zu benutzen NSDecimalNumber, der aufgrund seiner hervorragenden Rundung Funktionen.

Nicht als Mathematiker durch temperament, dachte ich, dass die Mantisse/exponent Paradigma sein könnte übertrieben;immer noch, googlin' herum, ich erkannte, dass die meisten Gespräche über Geld/Währung in Kakao wurden nach NSDecimalNumber.

Beachten Sie, dass die app, die ich arbeite, wird internationalisiert, so dass die Möglichkeit, zu zählen, den Betrag in Cent ist nicht wirklich rentabel, für die monetäre Struktur hängt stark von der locale verwendet.

Ich bin zu 90% sicher, dass ich brauchen, um mit zu gehen NSDecimalNumber, aber da fand ich keine eindeutige Antwort auf die web - (so etwas wie:"wenn du den Umgang mit Geld, nutzen NSDecimalNumber!") Ich dachte, ich würde hier Fragen.Vielleicht ist die Antwort ist offensichtlich für die meisten, aber ich möchte sicher sein, bevor eine massive re-factoring meiner app.

Mich überzeugen :)

War es hilfreich?

Lösung

Marcus Zarra hat eine ziemlich klare Haltung dazu: "Wenn Sie den Umgang mit der Währung überhaupt, dann sollten Sie mit NSDecimalNumber." Sein Artikel hat mich inspiriert, zu schauen, NSDecimalNumber, und ich bin sehr beeindruckt.IEEE-floating-point-Fehler beim Umgang mit Basis-10-math wurden reizt mich für eine Weile (1 * (0.5 - 0.4 - 0.1) = -0.00000000000000002776) und NSDecimalNumber nicht mit Ihnen.

NSDecimalNumber nicht nur hinzufügen, ein paar Ziffern von binären floating-point Präzision, es ist tatsächlich nicht Basis 10 (math.Dieser entledigt sich der Fehler wie im obigen Beispiel gezeigt.

Nun, ich Schreibe eine symbolische Mathematik-Anwendung, so mein Wunsch für 30+ Dezimalstelle Präzision und keine sonderbaren floating-point-Fehler könnte eine Ausnahme sein, aber ich denke, es ist einen Blick Wert.Die Operationen sind ein wenig umständlicher als einfach, var = 1 + 2 Stil Mathematik, aber Sie sind immer noch überschaubar.Wenn Sie sind besorgt über die Zuteilung aller möglichen Instanzen während Sie Ihre mathematischen Operationen, NSDecimal ist der C-struct entspricht NSDecimalNumber und es sind C-Funktionen, die das tun, die genau die gleiche mathematische Operationen mit ihm.In meiner Erfahrung, diese sind ausreichend schnell für alle, aber die anspruchsvollsten Anwendungen (3,344,593 Ergänzungen/s, 254,017 Abteilungen/s auf einem MacBook Air, 281,555 Ergänzungen/s, 12,027 Abteilungen/s auf einem iPhone).

Als zusätzlichen bonus, NSDecimalNumber ist descriptionWithLocale:Methode liefert einen string mit einer lokalisierten version der Reihe, einschließlich die richtige Dezimaltrennzeichen.Das gleiche gilt in umgekehrter für seine initWithString:locale:Methode.

Andere Tipps

Ja.Sie müssen verwenden

NSDecimalNumber und

nicht Doppel oder float wenn Sie sich mit der Währung auf iOS.

Warum ist das so??

Weil wir nicht wollen, um Dinge wie $9.9999999998 statt $10

Wie ist das passiert??

Floats und doubles sind Näherungswerte.Sie kommt immer mit einem Rundungsfehler.Das format Computern verwenden, zu speichern, decimals Ursache dieser rouding Fehler.Wenn Sie weitere Einzelheiten benötigen, Lesen

http://floating-point-gui.de/

Laut apple docs

NSDecimalNumber ist eine unveränderliche Unterklasse von NSNumber liefert einen objektorientierten wrapper für tun, base-10 Arithmetik.Eine Instanz kann für jede beliebige Zahl, die ausgedrückt werden kann als Mantisse x 10^exponent, wo die Mantisse ist eine dezimale ganze Zahl, die bis zu 38 Ziffern lang ist, und der exponent ist eine ganze Zahl von -128 bis 127.wrapper for doing base-10 Arithmetik.

So NSDecimalNumber ist recommonded für den Umgang mit der Währung.

(Angepasst von meinem Kommentar zu der anderen Antwort.)

Ja, sollten Sie.Eine Integrale Anzahl von pennies funktioniert nur so lange, wie Sie brauchen nicht zu vertreten, sagen wir, ein halbes Prozent.Wenn das passiert, Sie könnten es ändern, um zu zählen halbe Cent, aber was, wenn Sie dann müssen, stellen ein Viertel-cent-oder ein Achtel von ein cent?

Die einzig richtige Lösung ist NSDecimalNumber (oder etwas ähnliches), das schiebt das problem zu 10^-128¢ (D. H.,
0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000001¢).

(Eine andere Möglichkeit wäre, eine beliebige Präzision arithmetische, aber das erfordert eine separate Bibliothek, wie die GNU MP-Bignum-Bibliothek.GMP-ist unter der GNU LGPL.Ich habe noch nie verwendet, die Bibliothek und weiß nicht genau, wie es funktioniert, so dass ich nicht sagen konnte, wie gut es für Sie arbeiten würde.)

[Bearbeiten:Offenbar mindestens eine person—Brad Larson—denkt, ich spreche binary floating-point irgendwo in dieser Antwort.Ich bin es nicht.]

Eine bessere Frage ist, Wann sollte Sie nicht verwenden NSDecimalNumber mit Geld umzugehen.Die kurze Antwort auf diese Frage ist, dass, wenn Sie können nicht dulden, den performance-overhead von NSDecimalNumber und Sie kümmern sich nicht um kleine Rundungsfehler, weil Sie nie den Umgang mit mehr als ein paar Ziffern der Präzision.Die noch kürzere Antwort ist, sollten Sie immer verwenden NSDecimalNumber beim Umgang mit Geld.

Ich habe herausgefunden, dass es bequem zu bedienen eine ganze Zahl repräsentiert die Anzahl der cents und dann dividieren durch 100 für die Präsentation.Vermeidet das ganze Thema.

VISA, Mastercard und die anderen integer-Werte, indem Sie Mengen.Es ist bis zu sender und Empfänger zu analysieren amouts richtig laut Währung exponent (dividieren oder multiplizieren Sie mit 10^num, wobei num - ist ein exponent der Währung).Beachten Sie, dass unterschiedliche Währungen haben unterschiedliche Exponenten.In der Regel es ist 2 (also wir teilen geteilt und mit 100 multipliziert), aber einige Währungen haben, exponent = 0 (VND,etc), oder = 3.

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