Welchen Datentyp sollte ich für die Spielwährung verwenden?


96

Sollte in einem einfachen Geschäftssimulationsspiel (in Java + Slick2D integriert) der aktuelle Geldbetrag eines Spielers als floatoder als intoder als etwas anderes gespeichert werden ?

In meinem Anwendungsfall werden für die meisten Transaktionen Cents verwendet (0,50 USD, 1,20 USD usw.), und einfache Zinsberechnungen sind erforderlich.

Ich habe Leute gesehen, die sagten, Sie sollten niemals floatals Währung verwenden, und Leute, die sagten, Sie sollten niemals intals Währung verwenden. Ich habe das Gefühl, ich sollte intalle erforderlichen Prozentberechnungen verwenden und runden. Was soll ich benutzen?


2
Diese Frage wurde auf StackOverflow diskutiert. BigDecimal scheint der richtige Weg zu sein. stackoverflow.com/questions/285680/…
Ade Miller

2
Hat Java nicht einen CurrencyTyp wie Delphi's, der skalierte Festkomma-Mathematik verwendet, um Dezimal-Mathematik ohne die mit Gleitkomma verbundenen Genauigkeitsprobleme zu erhalten?
Mason Wheeler

1
Es ist ein Spiel. Das Rechnungswesen wird Sie nicht für einen abgerundeten Cent lynchen, und daher spielen die normalen Gründe gegen die Verwendung von Gleitkommazahlen für Währungen keine Rolle.
Loren Pechtel

@ MasonWheeler: Java hat BigDecimalfür diese Art von Problemen.
Martin Schröder

Antworten:


92

Sie können intalles in Cent verwenden und berücksichtigen. 1,20 US-Dollar sind nur 120 Cent. Bei der Anzeige geben Sie die Dezimalstelle dort ein, wo sie hingehört.

Zinsberechnungen würden nur entweder abgeschnitten oder aufgerundet. Damit

newAmt = round( 120 cents * 1.04 ) = round( 124.8 ) = 125 cents

Auf diese Weise bleiben keine unordentlichen Dezimalstellen immer hängen. Sie könnten reich werden, indem Sie das nicht angerechnete Geld (aufgrund von Abrundungen) auf Ihr eigenes Bankkonto einzahlen


3
Wenn Sie verwenden, roundgibt es keinen wirklichen Grund, auf den Sie sich besinnen sollten int, gibt es dann einen?
Sam Hocevar

19
+1. Gleitkommazahlen verfälschen Gleichheitsvergleiche, sind schwieriger zu formatieren und führen mit der Zeit zu lustigen Rundungsfehlern. Es ist besser, das alles selbst zu machen, damit du später keine Beschwerden bekommst. Es ist wirklich nicht viel Arbeit.
Dobes Vandermeer

+1. Klingt nach einem guten Weg für mein Spiel. Ich kümmere mich selbst um das Abrunden der Ints und halte mich von allen Problemen mit dem Schwimmer fern.
Lucas Tulio

Nur ein Haftungsausschluss: Ich habe die richtige Antwort auf diese Frage geändert, weil es das war, was ich verwendet habe. Es ist viel einfacher und im Kontext eines so einfachen Spiels spielen die nicht berücksichtigten Dezimalstellen keine Rolle.
Lucas Tulio

3
Verwenden Sie jedoch Basispunkte statt Cent (wobei 100 Basispunkte = 1 Cent) mit einem Faktor von 10.000 anstelle von 100. Dies ist nach GAAP für alle Finanz-, Bank- oder Buchhaltungsanwendungen erforderlich.
Pieter Geerkens

66

Okay, ich werde hineinspringen.

Mein Rat: Es ist ein Spiel. Nehmen Sie es einfach und verwenden Sie double.

Hier ist meine Begründung:

  • floatEs gibt ein Präzisionsproblem, das beim Hinzufügen von Einheiten zu Millionen auftritt. Obwohl es harmlos ist, würde ich diesen Typ vermeiden. doublefängt nur an, Probleme um die Quintillons (eine Milliarde Milliarden) zu bekommen.
  • Da Sie Zinssätze haben werden, benötigen Sie ohnehin eine theoretisch unendliche Genauigkeit: Bei 4% Zinssätzen werden 100 $ zu 104 $, dann zu 108,16 $, dann zu 112,4864 $ usw. Dies macht intund longunbrauchbar, weil Sie nicht wissen, wo Sie aufhören sollen die Dezimalstellen.
  • BigDecimalgibt Ihnen eine willkürliche Präzision, wird aber schmerzhaft langsam, es sei denn, Sie klemmen die Präzision zu einem bestimmten Zeitpunkt. Was sind die Rundungsregeln? Wie wählen Sie, wo Sie anhalten möchten? Lohnt es sich, mehr Präzisionsbits zu haben als double? Ich glaube nicht.

Der Grund, warum Festkomma-Arithmetik in Finanzanwendungen verwendet wird, liegt darin, dass sie deterministisch sind. Die Rundungsregeln sind, manchmal gesetzlich, perfekt definiert und müssen strikt angewendet werden, aber irgendwann tritt immer noch eine Rundung auf. Jedes Argument für einen bestimmten Typ, das auf Präzision basiert, ist wahrscheinlich falsch. Alle Typen haben Genauigkeitsprobleme mit der Art der Berechnungen, die Sie durchführen werden.

Praxisbeispiele

Ich sehe etliche Kommentare, die Dinge über Rundung oder Genauigkeit behaupten, mit denen ich nicht einverstanden bin. Hier sind einige zusätzliche Beispiele, um zu veranschaulichen, was ich meine.

Speichern : Wenn Ihre Basiseinheit der Cent ist, möchten Sie beim Speichern der Werte wahrscheinlich auf den nächsten Cent runden:

void SetValue(double v) { m_value = round(v * 100.0) / 100.0; }

Sie werden absolut keine Rundungsprobleme bekommen, wenn Sie diese Methode anwenden, die Sie nicht auch mit einem Integer-Typ hätten.

Abrufen : Alle Berechnungen können direkt mit den Doppelwerten ohne Konvertierungen durchgeführt werden:

double value = data.GetValue();
value = value / 3.0 * 12.0;
[...]
data.SetValue(value);

Beachten Sie, dass der obige Code nicht , wenn Sie ersetzen funktioniert doublemit int64_t: Es wird eine implizite Konvertierung sein double, dann Abschneiden zu int64_t, mit einem möglichen Verlust von information.data.GetValue ()

Vergleichen : Vergleiche sind das Richtige für Gleitkommatypen. Ich schlage vor, eine Vergleichsmethode wie diese zu verwenden:

/* Are values equal to a tenth of a cent? */
bool AreCurrencyValuesEqual(double a, double b) { return abs(a - b) < 0.001; }

Rundung der Fairness

Angenommen, Sie haben 9,99 USD auf dem Konto mit 4% Zinsen. Wie viel sollte der Spieler verdienen? Mit Integer-Rundung erhalten Sie $ 0,03; mit Gleitkomma-Rundung erhalten Sie 0,04 $. Letzteres halte ich für fairer.


4
+1. Die einzige Klarstellung, die ich hinzufügen möchte, ist, dass genau wie die Finanzanwendungen bestimmten vordefinierten Anforderungen entsprechen, auch der Rundungsalgorithmus. Wenn es sich bei dem Spiel um ein Casino handelt, entspricht es ähnlichen Standards und Double ist keine Option.
Ivaylo Slavov

2
Sie müssen noch über Rundungsregeln nachdenken, um die Benutzeroberfläche zu formatieren. Weil es immer einen Bruchteil von Spielern gibt, die versuchen, ein Spiel als Tabellenkalkulation zu behandeln, wenn Sie es nicht mit Leuten zu tun haben möchten, die schreiend auf und ab springen, wenn sie feststellen, dass Ihr Backend nicht die gleiche Präzision wie Ihre Benutzeroberfläche verwendet, was zur Folge hat 'falsche' ergebnisse werden angezeigt. Um sie möglichst leise darzustellen, sollten Sie dieselbe interne und externe Darstellung verwenden, dh ein festes Punktformat verwenden. Wenn die Leistung nicht zum Problem wird, ist BigDecimal die beste Wahl.
Dan Neely

10
Ich bin mit dieser Antwort nicht einverstanden. Es treten Rundungsprobleme auf, und wenn sie sinken und Sie keine zusätzliche Rundung verwenden, können aus 1,00 US-Dollar plötzlich 0,99 US-Dollar werden. Am wichtigsten ist jedoch, dass willkürliche Dezimalstellen, die langsam sind, (fast) keine Rolle spielen. Wir sind fast im Jahr 2013, und wenn Sie keine großen Faktorisierungen, Trigger oder Logarithmen über mehrere Millionen Zahlen mit Tausenden von Ziffern ausführen, werden Sie nicht einmal eine Beeinträchtigung der Leistung bemerken. Wie auch immer, einfach ist immer am besten, daher empfehle ich, alle Zahlen als Cent zu speichern. Auf diese Weise sind sie alle int_64ts.
Panda Pyjama

8
@Sam Als ich das letzte Mal mein Bankkonto überprüft habe, endete mein Kontostand nicht mit .0000000000000001. Realwährungssysteme müssen mit nicht teilbaren Einheiten arbeiten und das wird mit ganzen Zahlen korrekt dargestellt. Wenn Sie Währungsunterteilungen korrekt durchführen müssen (die in der realen Finanzwelt eigentlich gar nicht so häufig sind), müssen Sie sie durchführen, damit kein Geld verloren geht. Zum Beispiel 10/3 = 3+3+4oder 10/3 = 3+3+3 (+1). Bei allen anderen Operationen funktionieren Ganzzahlen im Gegensatz zu Gleitkommazahlen, die bei jeder Operation zu Rundungsproblemen führen können, einwandfrei.
Panda Pyjama

2
@SamHocevar 999 * 4/100. Sofern nicht durch eine Vorschrift festgelegt, wird davon ausgegangen, dass alle Rundungen zugunsten der Banken erfolgen.
Dan Neely,

21

Gleitkommatypen in Java ( float, double) sind für Währungen aus einem Hauptgrund nicht gut darstellbar: Es liegt ein Maschinenfehler bei der Rundung vor. Selbst wenn eine einfache Berechnung gibt eine ganze Anzahl - wie 12.0/2(6,0), die Gleitkomma könnte falsch um ihn herum (aufgrund tho der spezifischen Darstellung dieser Typen im Speicher) wie 6.0000000000001oder 5.999999999999998oder ähnliches. Dies ist ein Ergebnis der spezifischen Maschinenrundung, die im Prozessor auftritt und für den Computer, der sie berechnet hat, eindeutig ist. Normalerweise ist es selten ein Problem, mit diesen Werten zu arbeiten, da der Fehler ziemlich fahrlässig ist, aber es ist mühsam, dies dem Benutzer anzuzeigen.

Eine mögliche Lösung hierfür wäre die Verwendung einer benutzerdefinierten Implementierung des Gleitkomma-Datentyps wie BigDecimal. Es werden bessere Berechnungsmechanismen unterstützt, die die Rundungsfehler zumindest nicht maschinenspezifisch, sondern leistungsmäßig langsamer eingrenzen.

Wenn Sie eine hohe Produktivität benötigen, sollten Sie sich besser an die einfachen Typen halten. Falls Sie mit wichtigen Finanzdaten arbeiten und jeder Cent wichtig ist (wie eine Forex-Anwendung oder ein Kasinospiel), würde ich Ihnen empfehlen, Longoder zu verwenden long. LongDies würde es Ihnen ermöglichen, große Mengen und eine gute Präzision zu handhaben. Nehmen wir einmal an, Sie brauchen zum Beispiel 4 Stellen nach dem Komma. Sie müssen den Betrag nur mit 10000 multiplizieren. Ich habe Erfahrung in der Entwicklung von Online-Casinospielen und habe gesehen Long, dass er oft verwendet wird, um das Geld in Cent darzustellen . Bei Forex-Anwendungen ist die Genauigkeit wichtiger, sodass Sie einen größeren Multiplikator benötigen. Ganzzahlen sind jedoch frei von Rundungsproblemen (natürlich sollten Sie die manuelle Rundung wie in 3/2 selbst vornehmen).

Eine akzeptable Option wäre die Verwendung der Standardgleitkommatypen - Floatund Doublewenn die Leistung wichtiger ist als die Genauigkeit auf Hundertstel des Cent. Anschließend müssen Sie in Ihrer Anzeigelogik lediglich eine vordefinierte Formatierung verwenden , damit der Benutzer nicht von der Hässlichkeit potenzieller Maschinenrundungen beeinträchtigt wird.


4
+1 Ein Detail: "Nehmen wir an, Sie brauchen beispielsweise 4 Nachkommastellen. Sie müssen den Betrag nur mit 1000 multiplizieren." -> Dies nennt man Festpunkt.
Laurent Couvidou

1
@Sam, die Nummern wurden für den Beispieleinsatz zur Verfügung gestellt. Trotzdem habe ich persönlich seltsame Ergebnisse mit so einfachen Zahlen gesehen, aber es ist kein häufiges Szenario. Wenn Punkte kamen zu spielen schwimmen, das ist wahrscheinlich eher auftreten, sondern eher unwahrscheinlich zu beschmutzen
Ivaylo Slavov

2
@ Ivaylo Slavov, ich stimme Ihnen zu. In meiner Antwort habe ich gerade meine Meinung abgegeben. Ich liebe es zu diskutieren und die Bereitschaft zu haben, das Richtige zu tun. Danke auch für deine Meinung. :)
Md Mahbubur Rahman

1
@SamHocevar: Diese Argumentation funktioniert nicht in allen Fällen. Siehe: ideone.com/nI2ZOK
Samaursa

1
@SamHocevar: Das ist auch nicht garantiert. Zahlen innerhalb des Bereichs, die noch ganze Zahlen sind, häufen Fehler in der ersten Division an: ideone.com/AKbR7i
Samaursa

17

Bei Spielen im kleinen Maßstab und wenn die Prozessgeschwindigkeit ein wichtiges Problem ist (aufgrund der Präzision oder der Arbeit mit einem mathematischen Koprozessor kann dies schmerzhaft verlangsamen), reicht das Doppelte aus.

Bei Spielen in großem Maßstab (z. B. Social Games) und wenn die Verarbeitungsgeschwindigkeit nicht begrenzt ist, ist BigDecimal besser. Weil hier,

  • int oder long für Währungsberechnungen.
  • Floats und Doubles können die meisten reellen Basis-10-Zahlen nicht genau darstellen.

Ressourcen:

Von https://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency

Weil Floats und Doubles die meisten reellen Zahlen der Basis 10 nicht genau darstellen können.

So funktioniert eine IEEE-754-Gleitkommazahl: Sie reserviert ein Bit für das Vorzeichen, ein paar Bits zum Speichern eines Exponenten und den Rest für den tatsächlichen Bruch. Dies führt dazu, dass Zahlen in einer ähnlichen Form wie 1,45 * 10 ^ 4 dargestellt werden. mit der Ausnahme, dass die Basis 10 nicht ist, sondern zwei.

Alle reellen Dezimalzahlen können tatsächlich als exakte Bruchteile einer Zehnerpotenz betrachtet werden. Zum Beispiel ist 10.45 wirklich 1045/10 ^ 2. Und so wie manche Brüche nicht genau als Bruchteil einer Zehnerpotenz dargestellt werden können (ich denke an 1/3), können manche auch nicht genau als Bruchteil einer Zweierpotenz dargestellt werden. Als einfaches Beispiel können Sie 0.1 einfach nicht in einer Gleitkommavariable speichern. Sie erhalten den nächsten darstellbaren Wert, der ungefähr 0,0999999999999999996 beträgt, und die Software rundet ihn bei der Anzeige auf 0,1.

Wenn Sie jedoch mehr Additionen, Subtraktionen, Multiplikationen und Divisionen mit ungenauen Zahlen durchführen, verlieren Sie immer mehr an Präzision, je mehr sich die winzigen Fehler summieren. Dies macht Floats und Doubles ungeeignet für den Umgang mit Geld, wo perfekte Genauigkeit erforderlich ist.

Aus Bloch, J., Effective Java, 2. Aufl., Punkt 48:

The float and double types are particularly ill-suited for 

Währungsberechnungen, da es unmöglich ist, 0,1 (oder eine andere negative Zehnerpotenz) als Float oder Double genau darzustellen.

For example, suppose you have $1.03 and you spend 42c. How much money do you have left?

System.out.println(1.03 - .42);

prints out 0.6100000000000001.

The right way to solve this problem is to use BigDecimal, 

int oder long für Währungsberechnungen.

Schauen Sie sich auch an


Ich bin nur mit dem Teil nicht einverstanden, der für kleine Berechnungen geeignet ist. In meiner Praxis hat es sich als ausreichend erwiesen, um mit hoher Präzision und viel Geld umzugehen. Ja, die Verwendung mag etwas umständlich sein, schlägt aber BigDecimal in zwei entscheidenden Punkten: 1) Sie ist schneller (BigDecimal verwendet die Softwarerundung, die viel langsamer ist als die in float / double verwendete integrierte CPU-Rundung) und 2). Es ist schwieriger, BigDecimal in einer Datenbank beizubehalten, ohne an Genauigkeit zu verlieren - nicht alle Datenbanken unterstützen einen solchen "benutzerdefinierten" Typ. Long ist bekannt und wird in allen wichtigen Datenbanken unterstützt.
Ivaylo Slavov

@ Ivaylo Slavov, Entschuldigung für meinen Fehler. Ich habe meine Antwort aktualisiert.
Md Mahbubur Rahman

Keine Entschuldigung erforderlich, um einen anderen Ansatz für das gleiche Problem zu geben :)
Ivaylo Slavov

2
@ Ivaylo Slavov, ich stimme Ihnen zu. In meiner Antwort habe ich gerade meine Meinung abgegeben. Ich liebe es zu diskutieren und die Bereitschaft zu haben, das Richtige zu tun. Danke auch für deine Meinung. :)
Md Mahbubur Rahman

Ziel dieser Website ist es, die Probleme zu klären und dem OP zu helfen, die richtige Entscheidung zu treffen, abhängig vom jeweiligen Szenario. Wir können nur helfen, den Prozess zu beschleunigen :)
Ivaylo Slavov

13

Sie möchten speichern Sie Ihre Währung in longund berechnen Sie Ihre Währung in doublezumindest als Backup. Sie möchten, dass alle Transaktionen als stattfinden long.

Der Grund, warum Sie Ihre Währung speichern möchten, longist, dass Sie keine Währung verlieren möchten.

Nehmen wir an, Sie verwenden a doubleund haben kein Geld. Jemand gibt Ihnen drei Groschen und nimmt sie dann zurück.

You:       0.1+0.1+0.1-0.1-0.1-0.1 = 2.7755575615628914E-17

Naja, das ist nicht so cool. Vielleicht möchte jemand mit 10 US-Dollar sein Vermögen verschenken, indem er Ihnen zuerst drei Cent und dann 9,70 US-Dollar an einen anderen verschenkt.

Them: 10.0-0.1-0.1-0.1-9.7 = 1.7763568394002505E-15

Und dann gibst du ihnen die Groschen zurück:

Them: ...+0.1+0.1+0.1 = 0.3000000000000018

Das ist einfach kaputt.

Lassen Sie uns nun eine lange verwenden, und wir werden Zehntel Cent verfolgen (also 1 = 0,001 $). Geben wir jedem auf dem Planeten eine Milliarde, einhundertzwölf Millionen, fünfundsiebzigtausend, einhundertdreiundvierzig Dollar:

Us: 7000000000L*1112075143000L = 1 894 569 218 048

Warten Sie, wir können jedem mehr als eine Milliarde Dollar geben und nur etwas mehr als zwei ausgeben? Überlauf ist hier eine Katastrophe.

Also, wann immer Sie einen Geldbetrag berechnen, um ihn zu übertragen, zu verwenden doubleund Math.roundzu erhalten long. Richten Sie dann Salden ein (addieren und subtrahieren Sie beide Konten), indem Sie verwenden long.

Ihre Wirtschaft wird nicht auslaufen und auf eine Billiarde Dollar anwachsen.

Es gibt schwierigere Probleme - zum Beispiel, was machen Sie, wenn Sie zwanzig Zahlungen leisten? * - aber dies sollte Ihnen den Einstieg erleichtern.

* Sie berechnen, was eine Zahlung ist, rund um long; dann multipliziere mit 20.0und überprüfe, ob es in Reichweite ist; In diesem 20LFall multiplizieren Sie die Zahlung mit , um den von Ihrem Guthaben abgezogenen Betrag zu erhalten. Im Allgemeinen müssen alle Transaktionen so behandelt werden long, dass Sie wirklich alle einzelnen Transaktionen zusammenfassen müssen. Sie können als Abkürzung multiplizieren, aber Sie müssen sicherstellen, dass Sie keine Rundungsfehler hinzufügen und nicht überlaufen, was bedeutet, dass Sie dies überprüfen müssen, doublebevor Sie die eigentliche Berechnung mit ausführen long.


8

Ich würde sogar sagen, dass jeder Wert, der dem Benutzer angezeigt wird, fast immer eine ganze Zahl sein sollte. Geld ist nur das prominenteste Beispiel dafür. Wenn Sie einem Monster mit 900 HP viermal 225 Schadenspunkte zufügen und feststellen, dass noch 1 HP übrig sind, werden Sie von der Erfahrung ebenso abgezogen wie wenn Sie feststellen, dass Sie einen unsichtbaren Bruchteil eines Pennys sind, dem es an Leistung mangelt.

Auf der technischen Seite ist es meiner Meinung nach erwähnenswert, dass man nicht auf Floats zurückgreifen muss, um fortgeschrittene Dinge wie Interesse zu erledigen. Solange Sie genug Headroom in Ihrem gewählten Integer-Typ haben, wird eine Multiplikation und Division für eine Multiplikation mit einer Dezimalzahl stehen, zum Beispiel um 4% zu addieren, abgerundet:

number=(number*104)/100

4% addieren, gerundet durch Standardkonventionen:

number=(number*104+50)/100

Hier gibt es keine Fließkommaungenauigkeit, die Rundung ist immer exakt auf die .5Marke aufgeteilt.

Edit, die eigentliche Frage:

Ich fange an zu denken , zu sehen , wie die Debatte gegangen ist , dass umreißt , was die Frage dreht sich alles um kann nützlicher sein als eine einfache int/ floatAntwort. Im Kern der Frage geht es nicht um Datentypen, sondern darum, die Kontrolle über die Details eines Programms zu übernehmen.

Die Verwendung einer Ganzzahl zur Darstellung eines nicht ganzzahligen Werts zwingt den Programmierer, sich mit den Implementierungsdetails zu befassen. "Welche Präzision soll verwendet werden?" und "Welche Art zu runden?" sind Fragen, die explizit beantwortet werden müssen.

Ein Float dagegen zwingt den Programmierer nicht zur Sorge, er macht schon so ziemlich das, was man erwarten würde. Da ein Gleitkomma jedoch nicht unendlich genau ist, findet eine gewisse Rundung statt, und diese Rundung ist ziemlich unvorhersehbar.

Was passiert bei One Use Floats und möchten die Rundung steuern? Es erweist sich als fast unmöglich. Die einzige Möglichkeit, ein Float wirklich vorhersehbar zu machen, besteht darin, nur Werte zu verwenden, die in ganzen 2^ns dargestellt werden können. Aber diese Konstruktion macht die Verwendung von Schwimmern ziemlich schwierig.

Die Antwort auf die einfache Frage lautet also: Wenn Sie die Kontrolle übernehmen möchten, verwenden Sie Ganzzahlen, wenn nicht, verwenden Sie Gleitkommazahlen.

Aber die Frage, die diskutiert wird, ist nur eine andere Form der Frage: Wollen Sie die Kontrolle übernehmen?


5

Auch wenn es "nur ein Spiel" ist, würde ich Money Pattern von Martin Fowler verwenden, unterstützt durch eine lange.

Warum?

Lokalisierung (L10n): Mit diesem Muster können Sie Ihre Spielwährung leicht lokalisieren. Denken Sie an die alten Tycoon-Spiele wie "Transport Tycoon". Sie ermöglichen dem Spieler auf einfache Weise, die Währung im Spiel (dh von Britischem Pfund zu US-Dollar) zu ändern, um die Währung der realen Welt zu erfüllen.

Und

Der lange Datentyp ist eine 64-Bit-Zweierkomplement-Ganzzahl mit Vorzeichen. Es hat einen Mindestwert von -9.223.372.036.854.775.808 und einen Höchstwert von 9.223.372.036.854.775.807 (einschließlich) ( Java Tutorials )

Das heißt, Sie können 9.000-mal den aktuellen M2 US-Geldvorrat (~ 10.000 Milliarden Dollar) speichern . Geben Sie genügend Platz andere Weltwährung zu verwenden, wahrscheinlich, auch diejenigen , die hatte / hat Überblähung (Wenn neugierig, sehen nach dem Ersten Weltkrieg deutsche Inflation , wobei 1 Pfund Brot 3000000000 Mark war)

Lange ist leicht zu bestehen, sehr schnell und sollen Ihnen genug Platz gibt alle Interessen Berechnungen mit nur Integer - Arithmetik zu tun, gibt E - Business - Antwort eine Erklärung darüber , wie das zu tun.


2

Wie viel Arbeit möchten Sie dafür investieren? Wie wichtig ist Genauigkeit? Interessieren Sie sich für die Nachverfolgung der Bruchfehler, die bei der Rundung auftreten, und für die Ungenauigkeit der Darstellung von Dezimalzahlen in einem Binärsystem?

Letztendlich tendiere ich dazu, etwas mehr Zeit für das Codieren und Implementieren von Komponententests für "Eckfälle" und bekannte problematische Fälle aufzuwenden - daher würde ich in Form einer modifizierten BigInteger-Zahl denken, die beliebig große Mengen umfasst und die gebrochenen Bits entweder mit einem BigDecimal oder verwaltet ein BigRational-Teil (zwei BigInteger, einer für den Nenner und einer für den Zähler) - und Code einschließen, um den Bruchteil als tatsächlichen Bruch zu erhalten, indem (möglicherweise nur in regelmäßigen Abständen) ein nicht-gebrochener Teil zur Haupt-BigInteger hinzugefügt wird. Dann würde ich intern alles in Cent verfolgen, nur um die Bruchteile aus den GUI-Berechnungen herauszuhalten.

Wahrscheinlich viel zu komplex für ein (einfaches) Spiel - aber gut für eine Bibliothek, die als Open Source veröffentlicht wurde! Müsste nur Wege finden, um die Leistung im Umgang mit den Bruchteilen gut zu halten ...


1

Mit Sicherheit nicht schweben. Mit nur 7 Stellen haben Sie nur Genauigkeit wie:

12.345,67 123.456,7x

Sie sehen also, bereits mit 10 ^ 5 Dollar verlieren Sie den Überblick über Pennys. double ist für Spielzwecke verwendbar und aus Genauigkeitsgründen nicht im wirklichen Leben.

Aber long (und damit meine ich 64-Bit oder long long in C ++) reicht nicht aus, um Transaktionen zu verfolgen und zusammenzufassen. Es reicht aus, den Nettobestand eines Unternehmens zu halten, aber alle Transaktionen eines Jahres könnten überlaufen. Das hängt davon ab, wie groß Ihre finanzielle "Welt" im Spiel ist.


0

Eine andere Lösung, die ich hier hinzufügen werde, ist, eine Geldklasse zu machen. Die Klasse wäre so etwas wie (könnte sogar einfach eine Struktur sein).

class Money
{
     string currencyType; //the type of currency example USD could be an enum as well
     bool isNegativeValue;
     unsigned long int wholeUnits;
     unsigned short int partialUnits;
}

Auf diese Weise können Sie die Cent in diesem Fall als Ganzzahl und den gesamten Dollar als Ganzzahl darstellen. Da Sie ein separates Flag haben, um negativ zu sein, können Sie vorzeichenlose Ganzzahlen für Ihre Werte verwenden, die den möglichen Betrag verdoppeln (Sie können auch eine Zahlenklasse schreiben, die diese Idee auf Zahlen anwendet, um WIRKLICH große Zahlen zu erhalten). Alles, was Sie tun müssten, ist eine Überladung der mathematischen Operatoren, und Sie könnten dies wie jeden alten Datentyp verwenden. Es nimmt mehr Speicherplatz in Anspruch, erweitert aber die Grenzwerte.

Dies könnte weiter ausgebaut werden, um beispielsweise die Anzahl der Teileinheiten pro ganze Einheit einzuschließen, sodass Sie Währungen haben können, die sich auf etwas anderes als 100 Teileinheiten, in diesem Fall Cent, pro Dollar, aufteilen. Sie könnten beispielsweise 125 Floopies zu einem Flooper zusammensetzen.

Bearbeiten:

Ich werde die Idee dahingehend erweitern, dass Sie auch eine Art Nachschlagetabelle anzeigen können, auf die die Geldklasse zugreifen kann, um einen Wechselkurs für ihre Währung gegenüber allen anderen Währungen zu erhalten. Sie können dies in Ihre Operatorüberladungsfunktionen integrieren. Wenn Sie also automatisch versuchen, 4 US-Dollar zu 4 britischen Pfund hinzuzufügen, erhalten Sie automatisch 6,6 Pfund (zum Zeitpunkt des Schreibens).



-1

Verwenden Sie Klasse, es ist der beste Weg. Sie können die Ausführung Ihres Geldes verbergen, Sie können jederzeit doppelt / lang wechseln, was immer Sie wollen.

Beispiel

class Money
{
    private long count;//Store here what ever you want in what type you want i suggest long or int
    //methods constructors etc.
    public String print()
    {
        return count/100.F; //convert this to string
    }
}

In Ihrem Code verwenden Sie einfach Getter, es ist meiner Meinung nach besser und Sie können nützlichere Methoden speichern.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.