Verwenden Sie Float oder Decimal für die Buchhaltung.

75

Wir schreiben unser altes Buchhaltungssystem in VB.NET und SQL Server neu. Wir haben ein neues Team von .NET / SQL-Programmierern hinzugezogen, um das Umschreiben durchzuführen. Der größte Teil des Systems ist bereits mit den Dollarbeträgen unter Verwendung von Floats abgeschlossen. Die von mir programmierte Legacy-Systemsprache hatte kein Float, daher hätte ich wahrscheinlich eine Dezimalzahl verwendet.

Was ist Ihre Empfehlung?

Sollte der Datentyp Float oder Decimal für Dollarbeträge verwendet werden?

Was sind einige der Vor- und Nachteile für beide?

Ein Nachteil, der in unserem täglichen Scrum erwähnt wurde, war, dass Sie vorsichtig sein müssen, wenn Sie einen Betrag berechnen, der ein Ergebnis liefert, das über zwei Dezimalstellen liegt. Es hört sich so an, als müssten Sie den Betrag auf zwei Dezimalstellen runden.

Ein weiterer Nachteil ist, dass alle Anzeigen und gedruckten Beträge eine Formatanweisung haben müssen, die zwei Dezimalstellen anzeigt. Ich bemerkte einige Male, wo dies nicht getan wurde und die Mengen nicht korrekt aussahen. (dh 10,2 oder 10,2546)

Ein Profi ist, dass der Float nur 8 Bytes auf der Festplatte belegt, während die Dezimalstelle 9 Bytes belegt (Dezimalzahl 12,2).

Gerhard Weiss
quelle
5
Geh zurück und lass deine Schwimmer los.
Loren Pechtel

Antworten:

110

Sollte der Datentyp Float oder Decimal für Dollarbeträge verwendet werden?

Die Antwort ist einfach. Schwimmt nie. NIE !

Floats waren gemäß IEEE 754 immer binär, nur die neuen Standard- IEEE 754R definierten Dezimalformate. Viele der gebrochenen binären Teile können niemals der exakten Dezimaldarstellung entsprechen.
Jede Binärzahl kann als m/2^n( m, npositive ganze Zahlen) geschrieben werden, jede Dezimalzahl als m/(2^n*5^n).
Da Binärdateien keine Primzahl haben factor 5, können alle Binärzahlen genau durch Dezimalstellen dargestellt werden, aber nicht umgekehrt.

0.3 = 3/(2^1 * 5^1) = 0.3

0.3 = [0.25/0.5] [0.25/0.375] [0.25/3.125] [0.2825/3.125]

          1/4         1/8         1/16          1/32

Sie erhalten also eine Zahl, die entweder höher oder niedriger als die angegebene Dezimalzahl ist. Immer.

Warum spielt das eine Rolle ? Rundung.
Normale Rundung bedeutet 0..4 nach unten, 5..9 nach oben. Es spielt also eine Rolle, ob das Ergebnis entweder 0.049999999999... oder 0.0500000000... Sie wissen vielleicht, dass es 5 Cent bedeutet, aber der Computer weiß das nicht und rundet 0.4999... ab (falsch) und 0.5000... auf (richtig) ).
Da das Ergebnis von Gleitkommaberechnungen immer kleine Fehlerterme enthält, ist die Entscheidung reines Glück. Es wird hoffnungslos, wenn Sie eine dezimale Rund-zu-Gerade-Behandlung mit Binärzahlen wünschen.

Nicht überzeugt? Sie bestehen darauf, dass in Ihrem Kontosystem alles in Ordnung ist?
Aktiva und Passiva gleich? Ok, dann nimm jede der angegebenen formatierten Zahlen jedes Eintrags, analysiere sie und summiere sie mit einem unabhängigen Dezimalsystem! Vergleichen Sie das mit der formatierten Summe.
Ups, da stimmt etwas nicht, oder?

Für diese Berechnung war extreme Genauigkeit und Wiedergabetreue erforderlich (wir haben Oracle FLOAT verwendet), damit wir die "Milliardstel eines Pennys" aufzeichnen konnten, die akkumuliert wurden.

Hilft nicht gegen diesen Fehler. Da alle Menschen automatisch davon ausgehen, dass der Computer richtig summiert, prüft praktisch niemand unabhängig.

TSK
quelle
Stellen Sie jedoch sicher, dass Sie mindestens 4 Dezimalstellen im Dezimalfeld verwenden, wenn Sie Berechnungen durchführen möchten, insbesondere die Division.
HLGEM
1
Und stellen Sie sicher, dass Sie wissen, dass (standardmäßig) 0,045 $ Runden auf 0,04 $ und 0,055 $ Runden auf 0,06 $
Keith
7
Für diejenigen, die sich nicht sicher sind, was Keith meint, verwenden Dezimaltypen eine andere Art der Rundung. Es scheint allgemein als "Banker-Rundung" bezeichnet zu werden, aber Wikipedia hat eine Reihe alternativer Namen: runde halbe bis gerade, unvoreingenommene Rundung, konvergente Rundung, statistische Rundung, niederländische Rundung, Gaußsche Rundung oder Banker-Rundung ( en.wikipedia.org) / wiki /… ).
Patridge
2
Beachten Sie außerdem, dass Decimal.Round und String.Format unterschiedliche Ergebnisse liefern: Decimal.Round (0,045 M, 2) = 0,04 und String.Format ("{0: 0,00}", 0,045 M) = 0,05
Jason Massey
46

Dieses Foto antwortet:

Foto 1, CO

Dies ist eine andere Situation: Ein Mann aus Northampton erhielt einen Brief, in dem er sagte, sein Haus würde beschlagnahmt, wenn er nicht null Dollar und null Cent zahlen würde!

Foto 2, CO

Nakilon
quelle
3
Das brachte mich zum Lachen. Gut gemacht, Best Buy.
LittleBobbyTables - Au Revoir
17
Ich habe jeden Monat für das Jahr eine Rechnung über 0,01 USD von einer Telefongesellschaft erhalten. Also zahlte ich ihnen online 0,02 USD, bekam dann eine Rechnung für - 0,01 USD für sechs Monate, dann hörte es auf.
Neil McGuigan
22

Zuerst sollten Sie dies lesen, was jeder Informatiker über Gleitkomma-Arithmetik wissen sollte . Dann sollten Sie wirklich in Betracht ziehen, eine Art Festpunkt- / Zahlenpaket mit beliebiger Genauigkeit zu verwenden (z. B. Java BigNum, Python-Dezimalmodul), da Sie sonst in eine Welt voller Verletzungen geraten. Stellen Sie dann fest, ob die Verwendung des nativen SQL-Dezimaltyps ausreicht.

Floats / Doubles existieren (ed), um das schnelle x87 fp freizulegen, das jetzt ziemlich veraltet ist. Verwenden Sie sie nicht, wenn Sie sich um die Genauigkeit der Berechnungen kümmern und / oder ihre Einschränkungen nicht vollständig ausgleichen.

Rich Schuler
quelle
1
Während es nützlich ist, mehr über Gleitkomma zu lernen, ähnelt die Verwendung des Dezimaltyps in C # der Verwendung eines in die Sprache integrierten Festpunkt- / Zahlenpakets mit beliebiger Genauigkeit, wie Sie vorschlagen. Unter msdn.microsoft.com/en-us/library/system.decimal.aspx finden Sie eine Erklärung, wie Dezimalstellen genaue Zehnerpotenzen mit Dezimalstellen anstelle von Zweierpotenzen für die Dezimalkomponente speichern (es handelt sich im Grunde genommen um ein Int mit einer Dezimalplatzierungskomponente ).
Chris Moschini
1
"um das schnelle x87 fp freizulegen, das mittlerweile ziemlich veraltet ist", das sind einfach keine wahren Gleitkommazahlen, die immer noch einer der am häufigsten verwendeten Datentypen auf Computern sind, z. B. Simulationen, Spiele, Signalverarbeitung ...
markmnl
10

Als zusätzliche Warnung verwenden SQL Server und das .NET-Framework einen anderen Standardalgorithmus zum Runden. Stellen Sie sicher, dass Sie den Parameter MidPointRounding in Math.Round () auschecken. Das .NET-Framework verwendet standardmäßig den Bankers-Algorithmus und SQL Server verwendet die symmetrische algorithmische Rundung. Schauen Sie sich die Wikipedia - Artikel hier

Darrel Miller
quelle
7

Fragen Sie Ihre Buchhalter! Sie werden dich wegen der Verwendung von Float missbilligen. Verwenden Sie float wie NUR, wenn Sie nicht auf Genauigkeit achten. Obwohl ich immer dagegen wäre, wenn es um Geld geht.

In der Buchhaltungssoftware ist ein Float NICHT akzeptabel. Verwenden Sie eine Dezimalstelle mit 4 Dezimalstellen.


quelle
6

Gleitkommazahlen haben unerwartete irrationale Zahlen.

Zum Beispiel können Sie 1/3 nicht als Dezimalzahl speichern, es wäre 0,3333333333 ... (und so weiter)

Floats werden tatsächlich als Binärwert und Potenz von 2 Exponenten gespeichert.

Also wird 1,5 als 3 x 2 zu -1 (oder 3/2) gespeichert

Mit diesen Basis-2-Exponenten werden einige ungerade irrationale Zahlen erzeugt, zum Beispiel:

Konvertieren Sie 1.1 in einen Float und konvertieren Sie ihn dann wieder zurück. Ihr Ergebnis lautet ungefähr: 1.0999999999989

Dies liegt daran, dass die binäre Darstellung von 1.1 tatsächlich 154811237190861 x 2 ^ -47 ist, mehr als ein Double verarbeiten kann.

Mehr zu diesem Thema in meinem Blog , aber im Grunde genommen sind Dezimalstellen für die Speicherung besser geeignet.

Auf Microsoft SQL Server haben Sie den moneyDatentyp - dies ist normalerweise am besten für die finanzielle Speicherung geeignet. Es ist auf 4 Dezimalstellen genau.

Für Berechnungen haben Sie eher ein Problem - die Ungenauigkeit ist ein winziger Bruchteil, aber setzen Sie sie in eine Potenzfunktion und es wird schnell signifikant.

Dezimalstellen sind jedoch für keine Art von Mathematik sehr gut - es gibt zum Beispiel keine native Unterstützung für Dezimalstellen.

Keith
quelle
3
"irrational" ist nicht das Wort, nach dem Sie suchen. 1/3 ist immer noch rational, aber es hat keine endliche binäre Darstellung ...
Brian Postow
Ja, ich weiß - ich bin mir nur nicht sicher, wie ich es sonst nennen soll: Eine Nummer, die nicht dargestellt werden kann, ist etwas zu wortreich.
Keith
Sie sind Annäherungen, aber dann könnten auch Zahlen, die dargestellt werden könnten, angenähert werden. Eine tatsächliche irrationale Zahl ist eine Zahl, die unabhängig von der Basis nicht durch einen ganzzahligen Bruch dargestellt werden kann. Dies sind Zahlen, die in Basis 10 dargestellt werden können, aber nicht in Basis 2.
Keith
Eine Zahl mit einer nicht endenden Dezimaldarstellung - das ist zu wortreich!
Kenny Evitt
Vielleicht könnte man sagen, dass Gleitkommazahlen normalerweise unerwartete und irrelevante Bruchwerte speichern.
Kenny Evitt
5

Verwenden Sie den Dezimaltyp des SQL Servers .

Verwenden Sie kein Geld und schweben Sie nicht .

Geld verwendet 4 Dezimalstellen, ist schneller als die Verwendung von dezimal BUT leidet unter einigen offensichtlichen und einige nicht so offensichtliche Probleme mit Rundung ( siehe diese connect Ausgabe )

Mitch Wheat
quelle
Siehe @ David Thornleys Antwort. Es kann sein, dass die Geldart die Rechnungslegungskonventionen am ehesten wiedergibt, jedoch (in) ungefähr.
Roy Tinker
5

Was ich empfehlen würde, ist die Verwendung von 64-Bit-Ganzzahlen, die das Ganze in Cent speichern.

Joshua
quelle
Mit der offensichtlichen Einschränkung, dass Teil-Cent-Werte (dh 0,015 USD) überhaupt nicht dargestellt werden können. Eine vernünftige Einschränkung für die meisten Apps.
Rocketmonkeys
Einfache Lösung: Speichern Sie es in Tausenden von Cent. Ich speichere das Zeug in Millionstel der fraglichen Währung.
Marenz
1
Überprüfen Sie Ihren Überlauf. Millionstel Cent fließen bei etwas mehr als 20 Milliarden Dollar über. Tausend Cent bei 20 Billionen (was akzeptabel sein kann oder nicht), während Cent 20 Billiarden beträgt (was ich für sicher halte).
Joshua
@Marenz: In jedem Berechnungsstadium sollte es häufig möglich sein, eine Einheit mit minimaler Größe zu definieren, für die die Berechnung durchgeführt wird, und es dürfen keine Rundungsfehler jeglicher Größenordnung an anderen Punkten auftreten, als wenn die Dinge explizit sind gerundet. Wenn man fünftausend von etwas zu 3 für 1 USD kauft, sollte der Gesamtpreis normalerweise 1666,67 USD (5000/3, auf den Penny gerundet) und nicht 1666,66667 USD (5000/3, auf 1/1000 Penny gerundet) oder 1666,65 USD (0,33333 USD) betragen mal 5000).
Supercat
5

Ein bisschen Hintergrund hier ....

Kein Zahlensystem kann alle reellen Zahlen genau verarbeiten. Alle haben ihre Grenzen, und dies umfasst sowohl das Standard-IEEE-Gleitkomma als auch die vorzeichenbehaftete Dezimalstelle. Der IEEE-Gleitkommawert ist pro verwendetem Bit genauer, aber das spielt hier keine Rolle.

Die Finanzzahlen basieren auf jahrhundertelanger Papier- und Stiftpraxis mit entsprechenden Konventionen. Sie sind ziemlich genau, aber vor allem reproduzierbar. Zwei Buchhalter, die mit verschiedenen Nummern und Tarifen arbeiten, sollten dieselbe Nummer haben. Jeder Raum für Diskrepanzen ist Raum für Betrug.

Daher ist für Finanzberechnungen die richtige Antwort die gleiche Antwort wie ein CPA, der gut rechnet. Dies ist eine Dezimalarithmetik, kein IEEE-Gleitkomma.

David Thornley
quelle
4

Der einzige Grund, Float für Geld zu verwenden, ist, wenn Sie sich nicht für genaue Antworten interessieren.

David Singer
quelle
4

Gleitkommazahlen sind keine exakten Darstellungen, Präzisionsprobleme sind beispielsweise beim Hinzufügen sehr großer und sehr kleiner Werte möglich. Aus diesem Grund werden für die Währung Dezimaltypen empfohlen, auch wenn das Präzisionsproblem möglicherweise selten genug ist.

Zur Verdeutlichung speichert der dezimale 12,2-Typ diese 14 Ziffern genau, während der Float dies nicht tut, da er intern eine binäre Darstellung verwendet. Beispielsweise kann 0,01 nicht genau durch eine Gleitkommazahl dargestellt werden - die nächste Darstellung ist tatsächlich 0,0099999998

Niall
quelle
Dezimalstellen sind ebenfalls nicht genau, es sei denn, sie sind unendlich genau.
1800 INFORMATION
0.1 kann genau in einem Dezimalfeld gespeichert werden. Dezimalstellen sind nicht für jede Zahl genau , sondern für die meisten (einige?) Üblichen Geldbeträge. Manchmal.
Rocketmonkeys
4

Für ein Bankensystem, an dessen Entwicklung ich beteiligt war, war ich für den Teil "Zinsabgrenzung" des Systems verantwortlich. Mein Code berechnete jeden Tag, wie viel Zinsen auf den Saldo an diesem Tag angefallen waren.

Für diese Berechnung war extreme Genauigkeit und Wiedergabetreue erforderlich (wir haben Oracle FLOAT verwendet), damit wir die aufgelaufenen "Milliardstel eines Pennys" aufzeichnen konnten.

Wenn es darum ging, die Zinsen zu "aktivieren" (dh die Zinsen auf Ihr Konto zurückzuzahlen), wurde der Betrag auf den Cent gerundet. Der Datentyp für die Kontensalden betrug zwei Dezimalstellen. (Tatsächlich war es komplizierter, da es sich um ein Mehrwährungssystem handelte, das mit vielen Dezimalstellen funktionieren konnte - aber wir haben immer auf den "Penny" dieser Währung gerundet). Ja - dort, wo "Bruchteile" von Verlust und Gewinn waren, aber wenn die Computerzahlen aktualisiert wurden (Geld ausgezahlt oder eingezahlt), waren es immer ECHTE Geldwerte.

Dies stellte die Buchhalter, Wirtschaftsprüfer und Tester zufrieden.

Fragen Sie also Ihre Kunden. Sie werden Ihnen ihre Bank- / Buchhaltungsregeln und -praktiken mitteilen.

Kerl
quelle
Milliardstel eines Pennys sind 0,01 ^ e-9 - es gibt absolut keinen Grund, Oracle FLOAT hier für "extreme Genauigkeit und Wiedergabetreue" zu verwenden, da es sich um eine Gleitkommadarstellung handelt, bei der es sich eher um eine ungefähre als um eine exakte Zahl handelt. TSQLs DECIMAL (38,18) wäre genauer. Ohne dass Sie erklären, wie Sie mit mehreren Währungen umgegangen sind, bin ich skeptisch, dass Sie fehlerfrei sind. Wenn die Tester vom Euro in den Simbabwe-Dollar umrechnen würden, könnten sie ein echtes Rundungsproblem sehen.
John Zabroski
Zur Verdeutlichung habe ich Floats für den Zinsabgrenzungsprozess verwendet. Für die tatsächlichen Transaktionen wurden Dezimalstellen verwendet (als die aufgelaufenen Zinsen ausgezahlt wurden). Zu dieser Zeit war das System eine einheitliche Währung. Wenn ich wieder Zeit hätte, hätte ich wahrscheinlich keine Schwimmer benutzt. :)
Guy
3

Noch besser als die Verwendung von Dezimalstellen ist die Verwendung von einfachen alten Ganzzahlen (oder vielleicht einer Art Bigint). Auf diese Weise haben Sie immer die höchstmögliche Genauigkeit, aber die Genauigkeit kann angegeben werden. Zum Beispiel könnte die Zahl 100bedeuten 1.00, die wie folgt formatiert ist:

int cents = num % 100;
int dollars = (num - cents) / 100;
printf("%d.%02d", dollars, cents);

Wenn Sie mehr Präzision wünschen, können Sie die 100 in einen größeren Wert ändern, z. B.: 10 ^ n, wobei n die Anzahl der Dezimalstellen ist.

Peter Stuifzand
quelle
3
Sie sollten dies tun, wenn Sie keinen guten Festkommatyp haben. Der Vorteil ist, dass Sie bestimmen können, wo sich die Dezimalstelle befindet. Der Nachteil ist, dass Sie sie vermasseln werden. Wenn Sie einen Festkommatyp erhalten können, müssen Sie sich darüber keine Sorgen machen.
Michael Kohne
3

Eine andere Sache, die Sie in Buchhaltungssystemen beachten sollten, ist, dass niemand direkten Zugriff auf die Tabellen haben sollte. Dies bedeutet, dass der gesamte Zugriff auf das Buchhaltungssystem über gespeicherte Prozesse erfolgen muss. Dies verhindert Betrug und nicht nur SQl-Injektionsangriffe. Ein interner Benutzer, der Betrug begehen möchte, sollte niemals die Möglichkeit haben, Daten in den Datenbanktabellen direkt zu ändern. Dies ist eine kritische interne Kontrolle auf Ihrem System. Möchten Sie wirklich, dass ein verärgerter Mitarbeiter zum Backend Ihrer Datenbank wechselt und diese Schecks schreibt? Oder verbergen Sie, dass sie einem nicht autorisierten Anbieter eine Ausgabe genehmigt haben, wenn sie keine Genehmigungsberechtigung haben? Nur zwei Personen in Ihrer gesamten Organisation sollten in der Lage sein, direkt auf Daten in Ihrer Finanzdatenbank, Ihre Datenbank und seine Sicherung zuzugreifen. Wenn Sie viele dbas haben, sollten nur zwei von ihnen diesen Zugriff haben.

Ich erwähne dies, weil Ihre Programmierer, wenn sie Float in einem Buchhaltungssystem verwenden, wahrscheinlich mit der Idee der internen Kontrollen nicht vertraut sind und sie bei ihren Programmierbemühungen nicht berücksichtigt haben.

HLGEM
quelle
2

Sie können immer so etwas wie einen Geldtyp für .Net schreiben.

Schauen Sie sich diesen Artikel an: Ein Geldtyp für die CLR - Der Autor hat meiner Meinung nach hervorragende Arbeit geleistet.

Tomer Pintel
quelle
2

Ich hatte den Geldtyp von SQL zum Speichern von Geldwerten verwendet. Vor kurzem musste ich mit einer Reihe von Online-Zahlungssystemen arbeiten und habe festgestellt, dass einige von ihnen Ganzzahlen zum Speichern von Geldwerten verwenden. In meinen aktuellen und neuen Projekten habe ich angefangen, Ganzzahlen zu verwenden, und ich bin ziemlich zufrieden mit dieser Lösung.

George
quelle
Ich gehe davon aus, dass Sie das ROUND-Verb in Ihren Prozeduren verwenden?
Gerhard Weiss
Wenn Sie auf der SQL-Seite meinen, dann NEIN. Ich bevorzuge, dass der DAL die Ganzzahl wie in der DB zurückgibt. In der Business Logic-Ebene führe ich die Transformation durch. int cent = Wert% 100; int dollar = (Wert - Cent) / 100; Mit .NET 3.5 habe ich dafür eine Erweiterungsmethode.
George
2

Von den 100 Brüchen n / 100, wobei n eine natürliche Zahl ist, so dass 0 <= n und n <100, können nur vier als Gleitkommazahlen dargestellt werden. Schauen Sie sich die Ausgabe dieses C-Programms an:

#include <stdio.h>

int main()
{
    printf("Mapping 100 numbers between 0 and 1 ");
    printf("to their hexadecimal exponential form (HEF).\n");
    printf("Most of them do not equal their HEFs. That means ");
    printf("that their representations as floats ");
    printf("differ from their actual values.\n");
    double f = 0.01;
    int i;
    for (i = 0; i < 100; i++) {
        printf("%1.2f -> %a\n",f*i,f*i);
    }
    printf("Printing 128 'float-compatible' numbers ");
    printf("together with their HEFs for comparison.\n");
    f = 0x1p-7; // ==0.0071825
    for (i = 0; i < 0x80; i++) {
        printf("%1.7f -> %a\n",f*i,f*i);
    }
    return 0;
}
Lars Bohl
quelle
Aus diesem Grund habe ich den obigen Code kopiert und im Codepad ausgeführt. codepad.org/03hAQZwq Dies beinhaltet die Ausgabe.
Dominic K
1

Haben Sie darüber nachgedacht, den Gelddatentyp zum Speichern von Dollarbeträgen zu verwenden?

In Bezug auf die Con, dass die Dezimalstelle ein weiteres Byte einnimmt, würde ich sagen, dass es mir egal ist. In 1 Million Zeilen werden Sie nur noch 1 MB verwenden und der Speicher ist heutzutage sehr billig.

Espo
quelle
1
Verwenden Sie nicht den Datentyp Geld. (Es ist ein Kater von SyBase.)
Mitch Wheat
1

Was auch immer Sie tun, Sie müssen auf Rundungsfehler achten. Berechnen Sie mit einer höheren Genauigkeit, als Sie in anzeigen.

1800 INFORMATIONEN
quelle
1

Möglicherweise möchten Sie eine Form der Festkomma-Darstellung für Währungswerte verwenden. Sie sollten auch die Rundung von Banker untersuchen (auch als "Round Half Even" bezeichnet). Dadurch werden Verzerrungen vermieden, die bei der üblichen "Round Half Up" -Methode auftreten.

user6931
quelle
0

Verwenden Sie immer Dezimal. Float gibt Ihnen aufgrund von Rundungsproblemen ungenaue Werte.


quelle
0

Gleitkommazahlen können nur Zahlen darstellen, die eine Summe negativer Vielfacher der Basis sind - für binäre Gleitkommazahlen sind das natürlich zwei.

Es gibt nur vier Dezimalbrüche, die genau im binären Gleitkomma dargestellt werden können: 0, 0,25, 0,5 und 0,75. Alles andere ist eine Annäherung, genauso wie 0,3333 ... eine Annäherung für 1/3 in Dezimalarithmetik ist.

Gleitkomma ist eine gute Wahl für Berechnungen, bei denen die Skalierung des Ergebnisses wichtig ist. Es ist eine schlechte Wahl, wenn Sie versuchen, auf eine bestimmte Anzahl von Dezimalstellen genau zu sein.

Mike Dimmick
quelle
0

Dies ist ein ausgezeichneter Artikel, der beschreibt, wann float und decimal verwendet werden sollen . Float speichert einen ungefähren Wert und Dezimal speichert einen exakten Wert.

Zusammenfassend sollte für exakte Werte wie Geld eine Dezimalzahl verwendet werden, und für ungefähre Werte wie wissenschaftliche Messungen sollte float verwendet werden.

Hier ist ein interessantes Beispiel, das zeigt, dass sowohl float als auch decimal an Genauigkeit verlieren können. Wenn Sie eine Zahl hinzufügen, die keine Ganzzahl ist, und diese Zahl dann subtrahieren, verliert die Genauigkeit, während die Dezimalzahl dies nicht tut:

    DECLARE @Float1 float, @Float2 float, @Float3 float, @Float4 float; 
    SET @Float1 = 54; 
    SET @Float2 = 3.1; 
    SET @Float3 = 0 + @Float1 + @Float2; 
    SELECT @Float3 - @Float1 - @Float2 AS "Should be 0";

Should be 0 
---------------------- 
1.13797860024079E-15

Wenn Sie eine Nicht-Ganzzahl multiplizieren und durch dieselbe Zahl dividieren, verlieren Dezimalstellen an Genauigkeit, Floats nicht.

DECLARE @Fixed1 decimal(8,4), @Fixed2 decimal(8,4), @Fixed3 decimal(8,4); 
SET @Fixed1 = 54; 
SET @Fixed2 = 0.03; 
SET @Fixed3 = 1 * @Fixed1 / @Fixed2; 
SELECT @Fixed3 / @Fixed1 * @Fixed2 AS "Should be 1";

Should be 1 
--------------------------------------- 
0.99999999999999900
BrokeMyLegBiking
quelle
0

Ihre Buchhalter möchten steuern, wie Sie runden. Die Verwendung von float bedeutet, dass Sie ständig runden, normalerweise mit einer FORMAT()type-Anweisung, die nicht so ist, wie Sie es möchten (verwenden Sie floor/ ceilingstattdessen).

Sie haben Währungsdatentypen ( money, smallmoney), die anstelle von float oder real verwendet werden sollten. Durch das Speichern von Dezimalstellen (12,2) werden Ihre Rundungen beseitigt, aber auch in Zwischenschritten - was in einer Finanzanwendung wirklich nicht das ist, was Sie wollen.

David T. Macknet
quelle