货币格式:删除无关紧要的零
Currency Formatting: Remove insignificant Zeros
我用 {0:C5}
显示最多 5 位小数的货币值,但是当有不重要的零时,它们不应该显示。
对于简单的小数,我只是使用 {0:0.#####}
,但我需要它与货币格式化程序一起使用,因为它是一个多语言系统。
编辑:忘了说我正在使用复合格式 https://msdn.microsoft.com/en-us/library/txafckwd(v=vs.110).aspx
您可以在正常格式化后使用 .TrimEnd(new Char[] { '0' } )
去除前导零。
var number = (0.476434323).ToString("C5").TrimEnd(new Char[] { '0' } );
也许明确地输入货币符号?例如:
String.Format(cultureInfo, "{0}{1:0.#####}", cultureInfo.NumberFormat.CurrencySymbol, 1.00005M))
另见 How to Remove the Trailing Zeros of Precision From a C# Decimal
您可以从十进制值中检索有效数字的数量,然后用您得到的数字生成货币格式
private string GenerateCurrencyFormatFor(decimal value)
{
const decimal NORMALIZE_COEFFICENT = 1.000000000000000000000000000000000m;
const int MAX_DIGITS = 5;
decimal normalizeValue = value/ NORMALIZE_COEFFICENT;
var decimalBits = decimal.GetBits(normalizeValue);
var decimalScaleInfo = decimalBits[3];
var scaleInfoBytes = BitConverter.GetBytes(decimalScaleInfo);
var significantDigitsCount = (int)scaleInfoBytes[2];
var actualDigitsCount = Math.Min(significantDigitsCount, MAX_DIGITS);
return $"C{actualDigitsCount}";
}
当然你可以 "refactor" 即使在一个班轮中也能实现这个功能,但我想要它来展示这个想法。
那就用吧
var value = 123.4500m;
var currencyFormat = GenerateCurrencyFormatFor(value);
var printValue = value.ToString(currencyFormat);
// will print £123.45
var value = 123.1234567m; // will print £123,12346
一个解决方案是使用 IFormatProvider
和 ICustomFormatter
public class NumberFormatter : IFormatProvider, ICustomFormatter
{
//TODO: Get your own NumberFormatInfo from CurrentCulture instead of this.
private static readonly NumberFormatInfo NumberFormatInfo = CultureInfo.CreateSpecificCulture("en-US").NumberFormat;
public object GetFormat(Type formatType)
{
if (formatType != typeof(ICustomFormatter))
{
throw new InvalidOperationException("Invalid Format");
}
return this;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
var supportedTypes = new Type[] { typeof(decimal), typeof(double), typeof(int), typeof(float) };
if (!supportedTypes.Contains(arg.GetType()))
{
return null;
}
if (format.ToUpper() != "C")
{
return null;
}
var result = arg.ToString();
var isFraction = result.IndexOf(".", System.StringComparison.Ordinal) > 0;
if (isFraction)
{
result = RemoveTrailingZero(result);
var numberOfDigits = result.Substring(result.IndexOf(".", System.StringComparison.Ordinal) + 1).Length;
if (numberOfDigits < 5)
{
NumberFormatInfo.CurrencyDecimalDigits = numberOfDigits;
NumberFormatInfo.NumberDecimalDigits = numberOfDigits;
}
else
{
NumberFormatInfo.CurrencyDecimalDigits = 5;
NumberFormatInfo.NumberDecimalDigits = 5;
}
}
return Convert.ToDecimal(result).ToString("C", NumberFormatInfo);
}
private string RemoveTrailingZero(string number)
{
var lastIndexOfZero = number.LastIndexOf("0", System.StringComparison.Ordinal);
if (lastIndexOfZero == number.Length - 1)
{
number = number.Remove(lastIndexOfZero);
return RemoveTrailingZero(number);
}
else
{
return number;
}
}
}
下面是用法和输出
var numberFormatter = new NumberFormatter();
var amount = 10000.1230M;
Console.WriteLine(string.Format(numberFormatter, "Amount is {0:C}", amount));
amount = 10000.12305M;
Console.WriteLine(string.Format(numberFormatter, "Amount is {0:C}", amount));
amount = 10000.00M;
Console.WriteLine(string.Format(numberFormatter, "Amount is {0:C}", amount));
amount = 10000.1010M;
Console.WriteLine(string.Format(numberFormatter, "Amount is {0:C}", amount));
Amount is ,000.123
Amount is ,000.12305
Amount is ,000
Amount is ,000.101
我用 {0:C5}
显示最多 5 位小数的货币值,但是当有不重要的零时,它们不应该显示。
对于简单的小数,我只是使用 {0:0.#####}
,但我需要它与货币格式化程序一起使用,因为它是一个多语言系统。
编辑:忘了说我正在使用复合格式 https://msdn.microsoft.com/en-us/library/txafckwd(v=vs.110).aspx
您可以在正常格式化后使用 .TrimEnd(new Char[] { '0' } )
去除前导零。
var number = (0.476434323).ToString("C5").TrimEnd(new Char[] { '0' } );
也许明确地输入货币符号?例如:
String.Format(cultureInfo, "{0}{1:0.#####}", cultureInfo.NumberFormat.CurrencySymbol, 1.00005M))
另见 How to Remove the Trailing Zeros of Precision From a C# Decimal
您可以从十进制值中检索有效数字的数量,然后用您得到的数字生成货币格式
private string GenerateCurrencyFormatFor(decimal value)
{
const decimal NORMALIZE_COEFFICENT = 1.000000000000000000000000000000000m;
const int MAX_DIGITS = 5;
decimal normalizeValue = value/ NORMALIZE_COEFFICENT;
var decimalBits = decimal.GetBits(normalizeValue);
var decimalScaleInfo = decimalBits[3];
var scaleInfoBytes = BitConverter.GetBytes(decimalScaleInfo);
var significantDigitsCount = (int)scaleInfoBytes[2];
var actualDigitsCount = Math.Min(significantDigitsCount, MAX_DIGITS);
return $"C{actualDigitsCount}";
}
当然你可以 "refactor" 即使在一个班轮中也能实现这个功能,但我想要它来展示这个想法。
那就用吧
var value = 123.4500m;
var currencyFormat = GenerateCurrencyFormatFor(value);
var printValue = value.ToString(currencyFormat);
// will print £123.45
var value = 123.1234567m; // will print £123,12346
一个解决方案是使用 IFormatProvider
和 ICustomFormatter
public class NumberFormatter : IFormatProvider, ICustomFormatter
{
//TODO: Get your own NumberFormatInfo from CurrentCulture instead of this.
private static readonly NumberFormatInfo NumberFormatInfo = CultureInfo.CreateSpecificCulture("en-US").NumberFormat;
public object GetFormat(Type formatType)
{
if (formatType != typeof(ICustomFormatter))
{
throw new InvalidOperationException("Invalid Format");
}
return this;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
var supportedTypes = new Type[] { typeof(decimal), typeof(double), typeof(int), typeof(float) };
if (!supportedTypes.Contains(arg.GetType()))
{
return null;
}
if (format.ToUpper() != "C")
{
return null;
}
var result = arg.ToString();
var isFraction = result.IndexOf(".", System.StringComparison.Ordinal) > 0;
if (isFraction)
{
result = RemoveTrailingZero(result);
var numberOfDigits = result.Substring(result.IndexOf(".", System.StringComparison.Ordinal) + 1).Length;
if (numberOfDigits < 5)
{
NumberFormatInfo.CurrencyDecimalDigits = numberOfDigits;
NumberFormatInfo.NumberDecimalDigits = numberOfDigits;
}
else
{
NumberFormatInfo.CurrencyDecimalDigits = 5;
NumberFormatInfo.NumberDecimalDigits = 5;
}
}
return Convert.ToDecimal(result).ToString("C", NumberFormatInfo);
}
private string RemoveTrailingZero(string number)
{
var lastIndexOfZero = number.LastIndexOf("0", System.StringComparison.Ordinal);
if (lastIndexOfZero == number.Length - 1)
{
number = number.Remove(lastIndexOfZero);
return RemoveTrailingZero(number);
}
else
{
return number;
}
}
}
下面是用法和输出
var numberFormatter = new NumberFormatter();
var amount = 10000.1230M;
Console.WriteLine(string.Format(numberFormatter, "Amount is {0:C}", amount));
amount = 10000.12305M;
Console.WriteLine(string.Format(numberFormatter, "Amount is {0:C}", amount));
amount = 10000.00M;
Console.WriteLine(string.Format(numberFormatter, "Amount is {0:C}", amount));
amount = 10000.1010M;
Console.WriteLine(string.Format(numberFormatter, "Amount is {0:C}", amount));
Amount is ,000.123
Amount is ,000.12305
Amount is ,000
Amount is ,000.101