2010-04-08 1 views
9

Ну, правило «за деньги, всегда десятичную» не применяется внутри команды разработчиков Microsoft, потому что если бы это было:«За деньги, всегда десятичные»?

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

Financial.IPmt и все другие методы были бы получить/вернуть decimal и не double как есть.

Теперь я задаюсь вопросом, могу ли я использовать эти методы, не беспокоясь о круглых ошибках?

Должен ли я использовать некоторые другие библиотеки для работы с финансами? Если да, можете ли вы указать мне некоторые хорошие (для использования C#)?

+1

Мой полносимметричному не-а-VB-пользователь догадка бы, что финансовая библиотека вероятно обрабатывает хранилище правильно внутренне, но я бы не стал ставить на него. Вы бы хотели проверить, является ли внутренняя обработка согласованной или нет, прежде чем просто осудить ее на основе типа возврата. – Matchu

+18

Мое голосование за boolean - у вас либо есть деньги, либо у вас нет ;-) – scunliffe

+1

То же самое для VB и C# – Dryadwoods

ответ

3

Вы можете использовать этот класс:

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

Привет, что такое переменная Per? – cbp

+0

@cbp См. Функцию VB для [PPmt] (https://msdn.microsoft.com/en-us/library/microsoft.visualbasic.financial.ppmt.aspx), которая соответствует функции «PPmt» здесь (вторая функция), которая вызывает 'IPmt'. –

10

Вот интересная дискуссия по поводу именно этой теме: http://www.vbforums.com/showthread.php?t=524101

О 1/3 пути вниз кто-то объясняет, что он использует двойной, поскольку функции VB.NET были реализованы работать точно так же, как и VB6. VB6 не имеет десятичного типа, поэтому он использует double.

Так что, если точность важна, вы не должны не использовать.

Ответы на вопросы this question имеют несколько перспективных альтернатив - просто игнорируйте принятый ответ, который предполагает использование библиотеки VB.

Ранее связан вопрос был удален, так вот некоторые из предложений, я ссылающийся (примечание: Я не пробовал это, YMMV)

+0

У VB6 есть тип валюты, хотя это Int64 с четырьмя подразумеваемыми десятичными знаками. –

+0

Я решил написать свои собственные методы финансирования с десятичными значениями. Red Gate's.Net Reflector как полезный инструмент: D – Dryadwoods

8

правило использовать decimal для денег является полезным, поскольку большинство валют имеют десятичные единицы. Используя десятичную арифметику, вы избегаете введения и накопления ошибки округления.

Financial Class functions использование с плавающей точкой по нескольким причинам:

  • Они внутренне не накапливаются - они основаны на замкнутом виде экспоненциальной/логарифмическая вычисления, не итерации и суммирование по периодам.
  • Они, как правило, не используют или не дают точные десятичные значения. Например, точная десятичная годовая процентная ставка, деленная на 12 ежемесячных платежей, становится повторяющейся десятичной.
  • Они предназначены в первую очередь для поддержки принятия решений и, в конце концов, мало применимы к фактической бухгалтерской отчетности.

Pmt и округление может определить номинальную ежемесячную оплату, но как только эта сумма определяется, накопление баланса - платежи, процентные платежи применяются и т.д. - происходит в decimal. Кроме того, поздние или авансовые платежи, праздничные дни и другие подобные неравномерности аннулируют прогнозируемую амортизацию, предоставляемую финансовыми функциями.