2015-04-13 2 views
0

Возможно ли, что в .NET для форматирования наиболее компактного числа, например "G"eneral Number formatting, с дополнительным разделителем тысяч..NET Общее форматирование чисел с тысячами Separator

Я не могу использовать следующий

String.Format("{0:#,###.###}",32445.324777M) 

Потому что я получаю "32,445.325", и вместо того, чтобы результат я хочу должен быть "32.445,325777". Также следует работать с произвольным количеством значимых цифр в дробной части.

PS: Мне это нужно только для decimal.

+0

Вы адресация 2 проблемы с вашим вопросом: 1) переключатель группа разделители с десятичным разделителем (использование соответствующей культуры) и 2) не ограничивает количество знаков после запятой, от не явно, используя '' # ... –

ответ

5

В это место входит культура форматирования. Вам нужно получить спецификатор формата, соответствующий вашим требованиям. По умолчанию у вас есть текущая культура, культура пользовательского интерфейса или инвариантная культура. Результаты, которые вы получаете, подразумевают, что вы используете американскую культуру.

Если у вас есть определенная культура, которую вы хотите вывести на номер, используйте это. Если нет, то вы можете создать свой собственный:

var nfi = 
    new NumberFormatInfo 
    { 
    NumberDecimalSeparator = ",", 
    NumberGroupSeparator = "." 
    }; 

var ci = 
    new CultureInfo(CultureInfo.InvariantCulture.LCID) { NumberFormat = nfi }; 

return string.Format(ci, "{0:#,###.########}", 32445.324777M) 

Если вы хотите, чтобы также получить наиболее компактный номер, вы должны будете использовать свой собственный код. Самый простой способ - попробовать оба и вернуть меньшую результирующую строку.

Если вы хотите, вы можете использовать синтаксис string.Format тоже - вы можете написать свой собственный ICustomFormatter, чтобы справиться с этим:

void Main() 
{ 
    var number = 32445.324777M; 

    string.Format(new MyNumberFormatter(), "{0:MyG}", number).Dump(); 
} 

class MyNumberFormatter : IFormatProvider, ICustomFormatter 
{ 
    public object GetFormat(Type type) 
    { 
    return this; 
    } 

    public string Format(string fmt, object arg, IFormatProvider formatProvider) 
    { 
    if (fmt != "MyG" || !(arg is decimal)) return string.Format(CultureInfo.CurrentCulture, "{0:" + fmt + "}", arg); 

    return "Hi"; 
    } 
} 

Эта реализация немного Hacky, конечно, я уверен, что вы можете найти лучшие примеры. Но это действительно работает. В методе Format вы можете выбрать формат, который лучше подходит для данного номера, или даже просто попробовать что-то вроде обычного ToString("G", CultureInfo.InvariantCulture) и добавить десятичные разделители к этой строке. Независимо плывет лодка :)

2

От .NET documentation

«#» пользовательский формат спецификатор служит символом цифры-заполнителя. Если форматированное значение имеет цифру в позиции, где символ «#» отображается в строке формата, эта цифра копируется в в строке результатов.

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

Строка формата «##» приводит к округлению значения до ближайшей цифры, предшествующей десятичной, где всегда используется , округляющееся от нуля. Например, форматирование 34,5 с «##» приведет к значению 35.

Это невозможно форматировать неопределенное количество знаков после запятой с возможностями форматирования по умолчанию. Поэтому вам следует подумать о том, чтобы написать свою собственную реализацию, если это необходимо.

О десятичном и тысячном разделителях, это зависит от ваших системных настроек, но вы можете переопределить их, используя другую культуру, как @Luaan описал это в своем ответе.

Возможно, вы также должны изучить this answer.

1

Если вы хотите, чтобы полный контроль создал yoru собственный formatter lik ниже. См. Случай «U» для вашего формата.

public class CustomerFormatter : IFormatProvider, ICustomFormatter 
{ 
    public object GetFormat(Type formatType) 
    { 
     if (formatType == typeof(ICustomFormatter)) 
      return this; 
     else 
      return null; 
    } 

    public string Format(string format, 
          object arg, 
          IFormatProvider formatProvider) 
    { 
     if (!this.Equals(formatProvider)) 
     { 
      return null; 
     } 
     else 
     { 
      // generic formatter if no formater specified 
      if (String.IsNullOrEmpty(format)) 
       format = "G"; 

      // not a decimal type object 
      if (!(arg is decimal)) 
       return null; 

      // get value 
      decimal val = (decimal)arg; 

      // convert value into generic culture string for control of format 
      string valueString = val.ToString(); 

      // get string in required format type 
      format = format.ToUpper(); 
      switch (format) 
      { 
       // our user format 
       case "U": 

        // get decimals 
        string decimals = val.ToString("G", CultureInfo.InvariantCulture); 
        decimals = decimals.Substring(decimals.IndexOf('.') + 1); 

        // get current culture info 
        NumberFormatInfo nfi = new CultureInfo(CultureInfo.CurrentCulture.Name).NumberFormat; 

        // set our separators 
        nfi.NumberGroupSeparator = ","; 
        nfi.NumberDecimalSeparator = "."; 

        // set numebr of decimals 
        nfi.NumberDecimalDigits = decimals.Length; 

        // convert value to our format 
        valueString = val.ToString("N", nfi); 
        break; 
       default: 
        break; 
      } 

      return valueString; 
     } 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     decimal dec = 32445.324777M; 
     Console.WriteLine(String.Format(new CustomerFormatter(), "{0}", dec)); 
     Console.WriteLine(String.Format(new CustomerFormatter(), "{0:G}", dec)); 
     Console.WriteLine(String.Format(new CustomerFormatter(), "{0:U}", dec)); 
     Console.WriteLine(String.Format(new CustomerFormatter(), "{0:T}", dec)); 

     Console.ReadLine(); 
    } 
} 
Смежные вопросы