2009-07-24 9 views
2

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

Например (пример культуры EN-US)

Dim money = 1234.556789D 
money.ToString("C") ' Yields $1,234.56 (notice the rounding & truncating) 

money.ToString("C99") ' Yields $1,234.556789000000000000....0 -- close but not perfect, those trailing zeros are unwanted. 

' I want something that would result in this... 
money.ToString("??") ' Yields $1,234.56789 

' likewise.... 
money = 0.1D 
money.ToString("??") ' Yields $0.10 (notice that it at least matches the culture's currency format -- two decimal places) 

Предполагая, что все пользователи данного приложения будут использовать правила en_US я мог бы сделать это «??» быть чем-то жестко закодированным, как «$ #, ## 0.00 ############################################## ############################ "- но это приводит к отторжению желудка. Есть ли встроенный способ для выполнения того, что мне нужно?

+1

Я просмотрел справочную документацию около 20 минут и ничего не нашел. Сожалею. – Greg

+0

Я ценю ваше время Грег. Извините, что вы оставили меня (и меня) с пустыми руками. Я полагаю, что это не очень «нормальный», чтобы иметь такую ​​потребность, что означало бы, что структура не будет естественным образом заниматься этой функцией. Ну, как уже было сказано ниже, я закончил свое собственное решение до тех пор, пока Microsoft не подумает, что это будет потрясающе/полезно, чтобы испечь прямо в рамки;) – ckittel

ответ

1

Видя, что там, кажется, не быть встроенный способ сделать это, я в конечном итоге прокатки мой собственный метод расширения, который выглядит как ...

Public Function ToUnroundedCurrency(ByVal value As Decimal) As String 
    Dim valueAsString As String = value.ToString() ' Some loss of precision happens here, but it is not a concern. 

    Dim decimalLocation As Integer = valueAsString.IndexOf(".") 

    ' Get number of digits after the decimal place in the number 
    Dim numberOfDecimalPlaces As Integer = 0 
    If (decimalLocation > 0) Then numberOfDecimalPlaces = valueAsString.Length - decimalLocation - 1 

    ' The currency formatter has a limit of 99 decimal places -- due to the decimal -> ToString() conversion above, this will never happen, but being defensive anyway. 
    If (numberOfDecimalPlaces > 99) Then 
     numberOfDecimalPlaces = 99 
    ElseIf (numberOfDecimalPlaces < CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalDigits) Then 
     ' also make sure we at least have the minimum required decimal places 
     numberOfDecimalPlaces = CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalDigits 
    End If 

    Return value.ToString("C" & numberOfDecimalPlaces) 
End Function 

я отметил некоторые незначительную потерю точности. Мы (или кто-то, возможно,) не имели бы дробных значений, достаточных для того, чтобы справляться с ограничениями.

0

Да. Вот ответ с другого форума:

http://forums.asp.net/p/1266337/2380486.aspx

+0

Если вы имеете в виду делать что-то вроде ... Dim money = 1234.556789D Dim с = Новый Globalization.CultureInfo (System.Globalization.CultureInfo.CurrentCulture.Name) c.NumberFormat.CurrencyDecimalDigits = 99 x.ToString ("C", с) Тогда я получаю завершающие нули для всех не заполненных десятичной цифры. Это то, что вы предлагали, или я неправильно понял ссылку, которую вы мне прислали? – ckittel

1

ToString ("C20") - C принимает прецизионным SuffiX

EDIT: упс, не читал этот вопрос, по-видимому.

.ToString («C20»). Обрезка («0»), кажется, как исправить, но это не работает, когда вы используете string.Format ...

+1

Я думаю, он только хочет показать соответствующие цифры. Это * всегда * показывает 20 цифр. – Thorarin

+0

Правильно, это не сработало бы для меня. по словам Торарина. – ckittel

+0

.Trim ('0') превратит 0.1D в $ 0.1 вместо $ 0.10 ... Я тоже подумал об этом. money.ToString («C99»). TrimEnd («0» c) .. тогда я подумал о том, чтобы связать его с PadRight (n, «0»). – ckittel

2

Вы могли бы сделать что-то вроде этого ...

var money = 1234.556789D; 
Console.WriteLine(money.ToString(GetFormat(money))); 

money = .1D; 

Console.WriteLine(money.ToString(GetFormat(money))); 

используя следующий метод, чтобы получить строку формата ...

static string GetFormat(double input) 
{ 
    // get the number of decimal places to show 
    int length = input.ToString().Length - input.ToString().IndexOf(".") - 1; 

    // return the currency format string to use with decimal.ToString() 
    return string.Format("C{0}", length < 2 ? 2 : length); 
} 

Если вы хотите взять его на шаг дальше, вы также можете обернуть все это в метод расширения так что вам не нужно было звонить метод GetFormat() изнутри ToString() - это может сделать вещи немного более чистыми.

+0

Да, я, вероятно, должен был уточнить, что я мог бы сыграть свою роль, как ваш хороший пример/предложение здесь сделать это; если бы я согласился с тем, что он всегда будет в электронном формате. Я надеялся на что-то более «запеченное», так сказать, чтобы обращаться с другими культурами. Этот метод или одно подобное также будет работать с другими культурами, если я заменил все жестко кодированные значения текущими культурными. – ckittel

0

Вы можете попробовать написать регулярное выражение, чтобы избавиться от всех этих конечных 0.

Смежные вопросы