C#.NET动态尾随零?

时间:2015-01-28 16:47:38

标签: c# .net

我正在编写一个用于格式化数字的库。存在需要指定尾随零的数量的问题。这方面的一个例子是财务数据,其中一些价格显示超过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允许指定要显示的小数位数,我想我可以使用一些花哨的对数数学来确定是否应该显示小数位。我想我会看看是否有更好的解决方案。

2 个答案:

答案 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;
    }