Fraktionaler Teil von NSDecimalNumber

7

Ich verwende NSDecimalNumber, um einen Wert für die Währung zu speichern. Ich versuche eine Methode namens "Cents" zu schreiben, die den Dezimalteil der Zahl als NSString mit einer führenden 0 zurückgibt, wenn die Zahl & lt; 10. Also im Grunde

%Vor%

Und ich versuche eine Methode zu erstellen, die 01, 02, etc ... bis 99 als String zurückgibt. Ich kann nicht herausfinden, wie man die Mantisse als String in diesem Format zurückgibt. Ich habe das Gefühl, dass mir eine bequeme Methode fehlt, aber ich habe mir die Dokumentation noch einmal angeschaut und sehe nichts, was mich herausspringt.

    
JamesB41 18.03.2011, 17:34
quelle

5 Antworten

11

Update: Dies ist eine relativ alte Antwort, aber es sieht so aus, als würden die Leute es immer noch finden. Ich möchte dies auf Korrektheit aktualisieren - ich habe ursprünglich die Frage beantwortet, wie ich einfach demonstrierte, wie man bestimmte Dezimalstellen aus einem double herausziehen kann, aber ich befürworte dies nicht als eine Möglichkeit, Währungsinformationen darzustellen.

>

Nie verwenden Gleitkommazahlen, um Währungsinformationen darzustellen. Sobald Sie anfangen, mit Dezimalzahlen zu arbeiten (wie Sie es mit Dollars mit Cent tun würden), führen Sie mögliche Gleitkommafehler in Ihren Code ein. Ein Computer kann nicht alle Dezimalwerte genau darstellen ( 1/100.0 , z. B. 1 Cent, wird auf meinem Computer als 0.01000000000000000020816681711721685132943093776702880859375 dargestellt). Abhängig davon, welche Währungen Sie repräsentieren möchten, ist es immer korrekter, eine Menge in Bezug auf ihren Basisbetrag (in diesem Fall Cent) zu speichern.

Wenn Sie Ihre Dollarwerte in ganzzahligen Centwerten speichern, werden Sie bei den meisten Operationen nie auf Gleitkommafehler stoßen, und es ist trivial einfach, Cent in Dollars für die Formatierung umzuwandeln. Wenn Sie zum Beispiel Steuern anwenden oder Ihren Cent-Wert mit einem double multiplizieren möchten, tun Sie dies, um einen double -Wert zu erhalten, wenden Sie Runden des Bankers , um auf den nächsten Cent zu runden und zurück in eine Ganzzahl zu konvertieren.

Es wird komplizierter, wenn Sie versuchen, mehrere Währungen zu unterstützen, aber es gibt Möglichkeiten, damit umzugehen.

tl; dr Verwenden Sie keine Gleitkommazahlen, um die Währung darzustellen, und Sie werden viel glücklicher und korrekter sein. NSDecimalNumber kann genau (und genau) Dezimalwerte darstellen, aber sobald Sie in double / float konvertieren, laufen Sie Gefahr, Gleitkommafehler einzuführen.

Dies kann relativ einfach gemacht werden:

  1. Erhalte den double -Wert der Dezimalzahl (dies funktioniert, vorausgesetzt, die Zahl ist nicht zu groß, um sie in einem Doppel zu speichern).
  2. In einer separaten Variablen wird double auf eine ganze Zahl umgewandelt.
  3. Multiplizieren Sie beide Zahlen mit 100, um den Genauigkeitsverlust zu berücksichtigen (im Wesentlichen in Cents umrechnen) und subtrahieren Sie Dollar vom Original, um die Anzahl der Cents zu erhalten.
  4. Gibt eine Zeichenfolge zurück.

(Dies ist eine allgemeine Formel für das Arbeiten mit allen Dezimalzahlen - die Arbeit mit NSDecimalNumber erfordert nur ein wenig Klebstoffcode, um es zum Laufen zu bringen).

In der Praxis würde es so aussehen (in einer Kategorie NSDecimalNumber ):

%Vor%     
Itai Ferber 18.03.2011, 18:44
quelle
11

Dies ist eine sicherere Implementierung, die mit Werten arbeitet, die nicht in double passen:

%Vor%

Dies druckt 01 :

%Vor%     
hamstergene 12.08.2011 08:13
quelle
2

Ich stimme der Methode von Itai Ferber nicht zu, da die Verwendung von doubleValue methode von NSNumber zu einem Verlust der Genauigkeit wie 1.60 & gt; & gt; 1.5999999999, so wird Ihr Cents-Wert "59" sein. Stattdessen schneide ich "dollars" / "cents" aus string, erhalten mit NSNumberFormatter :

%Vor%     
Alex Rush 02.03.2013 11:17
quelle
1

Ich habe einen anderen Ansatz. Es funktioniert für mich, aber ich bin mir nicht sicher, ob es irgendwelche Probleme verursachen könnte? Ich lasse NSDecimalNumber den Wert direkt zurückgeben, indem ich einen ganzzahligen Wert zurückließe ...

e.G .:

%Vor%

Wäre dieser Ansatz teurer, da ich NSDecimalNumber zweimal konvertiere?

    
d.ennis 12.08.2011 07:21
quelle
1

Schnelle Version, mit Bonusfunktion, um auch nur den Dollar-Betrag zu erhalten.

%Vor%

Tests:

%Vor%     
Graham Perks 07.03.2016 21:15
quelle