我正在编写一个用于格式化数字的库。存在需要指定尾随零的数量的问题。这方面的一个例子是财务数据,其中一些价格显示超过2位小数,但只有前两位小数可以是尾随零。
示例(给定2个尾随零和精度4):
0.10000 => 0.10
0.11100 => 0.111
0.119 => 0.119
0.11119 => 0.1112
我也希望将它与" P"和" C" System.Globalization提供的格式。例子:
0.587" C" => $ 0.587
0.20" C" => $ 0.20
0.20001" C" => $ 0.20
0.48745" C" => $ 0.4875
或
0.587" P" => 58.70%
0.20" C" => 20.00%
0.20001" C" => 20.00%
0.48745" C" => 48.745%
我希望能够为库提供可变数量的尾随零。
我想利用内置功能,以便利用全球化。由于.ToString和String.Format允许指定要显示的小数位数,我想我可以使用一些花哨的对数数学来确定是否应该显示小数位。我想我会看看是否有更好的解决方案。
答案 0 :(得分:4)
您可以使用:
number.ToString("0.00##")
和
decimal.Parse(text)
例如
var inputs = new[] { "0.1000", "0.11100", "0.119", "0.11119" };
var numbers = inputs.Select(decimal.Parse);
var output = numbers.Select(x => x.ToString("0.00##"));
Console.WriteLine(String.Join(", ", output));
输出
0.10, 0.111, 0.119, 0.1112
就百分比和货币而言,我不相信有任何聪明的方法可以做到这一点,但以下内容可以与上述结合:
var symbol = CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol // $
// ...
var output = numbers.Select(x => symbol + x.ToString("0.00##"));
// ...
// ...
var numbers = inputs.Select(x => decimal.Parse(x) * 100);
// ...
答案 1 :(得分:0)
我最后写了一个简短的算法,它将吐出适当的精度。这可以与" PX"," NX"或" CX"用于全球化和内置的.ToString格式。它已经过多种数字的单元测试,因此非常强大。
/// <summary>Calculate the correct precision based on trailing zeroes and target precision
/// </summary>
/// <param name="number">the number to check (multiply by 100 if it is being formatted as a percent)</param>
/// <param name="trailingZeroes">the number of trailing zeroes</param>
/// <param name="precision">the number of decimal places to show</param>
/// <returns>
/// Argument Exception: trailing zero and precision cannot be less than one or greater than 99
/// Argument Exception: trailing zeros cannot be larger than the precision
/// </returns>
private int CalculatePrecision(double number, int trailingZeroes, int precision)
{
if (trailingZeroes < 0 || trailingZeroes > 99 || precision < 0 || precision > 99)
{
throw new ArgumentException("Trailing Zeroes and precision must be between 0 and 99.");
}
// make sure trailng zeroes is not larger than precision
trailingZeroes = Math.Min(trailingZeroes, precision);
// a temporary value for locating decimal places
double tempValue;
// just the decimal places
double allDecimalPlaces = number - Math.Floor(number);
// the individual decimal place at a given power of 10
double singleDecimalPlaceValue;
// search for the zeroes in the decimal places
for (int i = precision; i > trailingZeroes; i--)
{
// get just the decimal place that needs to be checked
tempValue = allDecimalPlaces * Math.Pow(10, i - 1);
singleDecimalPlaceValue = Math.Round((tempValue - Math.Floor(tempValue)) * 10);
// check for a 0 decimal or a 10 value (for floating point math)
if (singleDecimalPlaceValue != 0 && singleDecimalPlaceValue != 10)
{
return i;
}
}
// if all zeroes are found, return trailing zeroes
return trailingZeroes;
}