2010-04-08 9 views
9

Nun, die Regel „Für Geld, immer dezimal“ nicht in dem Microsoft-Entwicklungsteam angewandt, denn wenn es war: würden"Für Geld, immer dezimal"?

Namespace: Microsoft.VisualBasic 
Assembly: Microsoft.VisualBasic (in Microsoft.VisualBasic.dll) 

Financial.IPmt und alle anderen Methoden erhalten/Return decimal und nicht double wie es ist.

Jetzt frage ich mich, ob ich diese Methoden ohne Sorge mit runden Fehlern verwenden kann?

Sollte ich einige andere Bibliotheken verwenden, um mit Finanzen zu arbeiten? Wenn ja, könnten Sie mir ein paar gute Tipps geben (für C# verwenden)?

+1

Mein total-not-a-VB-Benutzer Vermutung, dass die Finanz Bibliothek wahrscheinlich richtig intern behandelt Lagerung sein würde, aber ich würde nicht auf sie wetten. Sie sollten überprüfen, ob die interne Behandlung konsistent ist oder nicht, bevor Sie sie nur auf der Grundlage des Rückgabetyps verurteilen. – Matchu

+18

Meine Stimme ist für boolean - Sie haben entweder Geld oder Sie nicht ;-) – scunliffe

+1

Es ist das gleiche für VB und C# – Dryadwoods

Antwort

3

können Sie diese Klasse verwenden:

public class Financial 
{ 
    #region Methods 

    public static decimal IPmt(decimal Rate, decimal Per, decimal NPer, decimal PV, decimal FV, FinancialEnumDueDate Due) 
    { 
     decimal num; 
     if (Due != FinancialEnumDueDate.EndOfPeriod) 
     { 
      num = 2; 
     } 
     else 
     { 
      num = 1; 
     } 
     if ((Per <= 0) || (Per >= (NPer + 1))) 
     { 
      //Argument_InvalidValue1= 

      throw new ArgumentException("Argument 'Per' is not a valid value."); 
     } 
     if ((Due != FinancialEnumDueDate.EndOfPeriod) && (Per == 1)) 
     { 
      return 0; 
     } 
     decimal pmt = Pmt(Rate, NPer, PV, FV, Due); 
     if (Due != FinancialEnumDueDate.EndOfPeriod) 
     { 
      PV += pmt; 
     } 
     return (FV_Internal(Rate, Per - num, pmt, PV, FinancialEnumDueDate.EndOfPeriod) * Rate); 
    } 

    public static decimal PPmt(decimal Rate, decimal Per, decimal NPer, decimal PV, decimal FV, FinancialEnumDueDate Due) 
    { 
     if ((Per <= 0) || (Per >= (NPer + 1))) 
     { 
      throw new ArgumentException("Argument 'Per' is not valid."); 
     } 
     decimal num2 = Pmt(Rate, NPer, PV, FV, Due); 
     decimal num = IPmt(Rate, Per, NPer, PV, FV, Due); 
     return (num2 - num); 
    } 

    static decimal FV_Internal(decimal Rate, decimal NPer, decimal Pmt, decimal PV, FinancialEnumDueDate Due) 
    { 
     decimal num; 
     if (Rate == 0) 
     { 
      return (-PV - (Pmt * NPer)); 
     } 
     if (Due != FinancialEnumDueDate.EndOfPeriod) 
     { 
      num = 1 + Rate; 
     } 
     else 
     { 
      num = 1; 
     } 
     decimal x = 1 + Rate; 
     decimal num2 = (decimal)Math.Pow((double)x, (double)NPer); 
     return ((-PV * num2) - (((Pmt/Rate) * num) * (num2 - 1))); 
    } 

    static decimal Pmt(decimal Rate, decimal NPer, decimal PV, decimal FV, FinancialEnumDueDate Due) 
    { 
     decimal num; 
     if (NPer == 0) 
     { 
      throw new ArgumentException("Argument NPer is not a valid value."); 
     } 
     if (Rate == 0) 
     { 
      return ((-FV - PV)/NPer); 
     } 
     if (Due != FinancialEnumDueDate.EndOfPeriod) 
     { 
      num = 1 + Rate; 
     } 
     else 
     { 
      num = 1; 
     } 
     decimal x = Rate + 1; 
     decimal num2 = (decimal)Math.Pow((double)x, (double)NPer); 
     return (((-FV - (PV * num2))/(num * (num2 - 1))) * Rate); 
    } 

    #endregion Methods 
} 
+0

Hallo, wofür ist die Per-Variable? – cbp

+0

@cbp Bitte beachten Sie die VB-Funktion für [PPmt] (https://msdn.microsoft.com/en-us/library/microsoft.visualbasic.financial.ppmt.aspx), die die Funktion "PPmt" hier (2nd Funktion), die 'IPmt' aufruft. –

10

Hier ist eine interessante Diskussion in Bezug auf genau dieses Thema: http://www.vbforums.com/showthread.php?t=524101

über ein Drittel des Weges nach unten jemand erklärt, dass es doppelt verwendet, weil die VB.NET funktioniert genau wie VB6 die gleiche Arbeit umgesetzt wurden. VB6 hat keinen Dezimaltyp, weshalb es double verwendet.

So scheint es, dass, wenn Genauigkeit wichtig ist, Sie nicht diese Funktionen verwenden sollten.

Die Antworten auf this question haben einige vielversprechende Alternativen - ignorieren Sie einfach die akzeptierte Antwort, die die Verwendung der VB-Bibliothek vorschlägt.

Die zuvor verknüpfte Frage wurde gelöscht, so dass hier einige der Vorschläge sind ich Referenzierung (Anmerkung: ich diese nicht versucht haben, YMMV)

+0

VB6 hat jedoch einen Währungstyp, der ein Int64 mit vier implizierten Dezimalstellen ist. –

+0

Ich entschied mich, meine eigenen Finanzmethoden mit Dezimalwerten zu schreiben. Red Gate's.Net Reflektor als hilfreiches Werkzeug: D – Dryadwoods

8

Die Regel decimal für Geld zu verwenden, ist hilfreich, da die meisten Währungen Dezimaleinheiten haben. Durch die Verwendung von Dezimalarithmetik vermeiden Sie das Einbringen und Akkumulieren von Rundungsfehlern.

Financial Class functions Verwendung Gleitkommazahlen für ein paar Gründe:

  • Sie intern nicht tun akkumulieren - sie basieren auf einer geschlossenen Form exponentielle/logarithmische Berechnung, nicht Iteration und Summierung über Perioden.
  • Sie neigen nicht zu verwenden oder genaue Dezimalwerte zu produzieren. Zum Beispiel wird ein exakter Dezimaljahreszinssatz geteilt durch 12 Monatszahlungen eine sich wiederholende Dezimalzahl.
  • Sie sind in erster Linie für die Entscheidungsunterstützung gedacht und haben am Ende wenig Anwendung auf die eigentliche Buchhaltung.

Pmt und Rundung kann die nominale monatliche Zahlung bestimmen, aber sobald dieser Betrag bestimmt wird, Balance Akkumulation - Zahlungen, Zinsen angelegt, usw. - geschieht in decimal. Auch verspätete oder geleistete Vorauszahlungen, Zahlungsfeiertage und andere solche Ungleichförmlichkeiten würden die von den Finanzfunktionen vorgesehene geplante Amortisation ungültig machen.