【问题标题】:Best way to display decimal without trailing zeroes显示小数而没有尾随零的最佳方法
【发布时间】:2011-03-07 11:39:04
【问题描述】:

是否有一个显示格式化程序可以在 c# 中将小数作为这些字符串表示形式输出而不进行任何舍入?

// decimal -> string

20 -> 20
20.00 -> 20
20.5 -> 20.5
20.5000 -> 20.5
20.125 -> 20.125
20.12500 -> 20.125
0.000 -> 0

{0.#} 将四舍五入,并且使用某些 Trim 类型的函数将不适用于网格中绑定的数字列。

【问题讨论】:

    标签: c# formatting decimal


    【解决方案1】:

    您是否有需要显示的最大小数位数? (您的示例最多为 5 个)。

    如果是这样,我认为使用“0.#####”进行格式化会满足您的要求。

        static void Main(string[] args)
        {
            var dList = new decimal[] { 20, 20.00m, 20.5m, 20.5000m, 20.125m, 20.12500m, 0.000m };
    
            foreach (var d in dList)
                Console.WriteLine(d.ToString("0.#####"));
        }
    

    【讨论】:

    • 而且您总是可以在格式中抛出大量*数量的 # 符号。 *不科学
    • +1 - 顺便说一下,您不需要前导 #。 “0.#####”的工作原理相同。无论哪种方式,这确实从零开始(仅供参考)。
    • @TrueWill 实际上它确实有所作为。 d==0.1m 然后 "0.#" 呈现 "0.1" 和 "#.#" 呈现 ".1" 没有前导 0。都不是对或错,只取决于你想要什么。
    【解决方案2】:

    我刚刚学会了如何正确使用G 格式说明符。请参阅MSDN Documentation。后面有一条注释指出,当未指定精度时,将为十进制类型保留尾随零。我不知道他们为什么要这样做,但是为我们的精度指定最大位数应该可以解决这个问题。所以对于格式化小数,G29 是最好的选择。

    decimal test = 20.5000m;
    test.ToString("G"); // outputs 20.5000 like the documentation says it should
    test.ToString("G29"); // outputs 20.5 which is exactly what we want
    

    【讨论】:

    • 这会导致 0.00001 显示为 1E-05
    【解决方案3】:

    这种字符串格式应该会让你开心:“0.############################”。请记住,小数最多可以有 29 个有效数字。

    例子:

    ? (1000000.00000000000050000000000m).ToString("0.#############################")
    -> 1000000.0000000000005
    
    ? (1000000.00000000000050000000001m).ToString("0.#############################")
    -> 1000000.0000000000005
    
    ? (1000000.0000000000005000000001m).ToString("0.#############################")
    -> 1000000.0000000000005000000001
    
    ? (9223372036854775807.0000000001m).ToString("0.#############################")
    -> 9223372036854775807
    
    ? (9223372036854775807.000000001m).ToString("0.#############################")
    -> 9223372036854775807.000000001
    

    【讨论】:

    • 这是对这个问题最一般的回答。不知道为什么这不是十进制的默认“G”格式。尾随零不添加任何信息。 Microsoft 文档对小数有一个奇怪的警告:docs.microsoft.com/en-us/dotnet/standard/base-types/… 但是,如果数字是 Decimal 并且省略了精度说明符,则始终使用定点表示法并保留尾随零。
    【解决方案4】:

    这是我在上面看到的另一种变体。在我的情况下,我需要保留小数点右侧的所有有效数字,这意味着在最高有效数字之后删除所有零。只是觉得分享会很好。虽然我不能保证这样做的效率,但是当你试图达到美学的时候,你已经几乎被低效率诅咒了。

    public static string ToTrimmedString(this decimal target)
    {
        string strValue = target.ToString(); //Get the stock string
    
        //If there is a decimal point present
        if (strValue.Contains("."))
        {
            //Remove all trailing zeros
            strValue = strValue.TrimEnd('0');
    
            //If all we are left with is a decimal point
            if (strValue.EndsWith(".")) //then remove it
                strValue = strValue.TrimEnd('.');
        }
    
        return strValue;
    }
    

    就是这样,只是想投入我的两分钱。

    【讨论】:

      【解决方案5】:

      另一种解决方案,基于dyslexicanaboko's 答案,但独立于当前文化:

      public static string ToTrimmedString(this decimal num)
      {
          string str = num.ToString();
          string decimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
          if (str.Contains(decimalSeparator))
          {
              str = str.TrimEnd('0');
              if(str.EndsWith(decimalSeparator))
              {
                  str = str.RemoveFromEnd(1);
              }
          }
          return str;
      }
      
      public static string RemoveFromEnd(this string str, int characterCount)
      {
          return str.Remove(str.Length - characterCount, characterCount);
      }
      

      【讨论】:

      • 太棒了。除了 SqlDecimal 它是 CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator 尽管区域设置。
      【解决方案6】:

      扩展方法:

      public static class Extensions
      {
          public static string TrimDouble(this string temp)
          {
              var value = temp.IndexOf('.') == -1 ? temp : temp.TrimEnd('.', '0');
              return value == string.Empty ? "0" : value;
          }
      }
      

      示例代码:

      double[] dvalues = {20, 20.00, 20.5, 20.5000, 20.125, 20.125000, 0.000};
      foreach (var value in dvalues)
          Console.WriteLine(string.Format("{0} --> {1}", value, value.ToString().TrimDouble()));
      
      Console.WriteLine("==================");
      
      string[] svalues = {"20", "20.00", "20.5", "20.5000", "20.125", "20.125000", "0.000"};
      foreach (var value in svalues)
          Console.WriteLine(string.Format("{0} --> {1}", value, value.TrimDouble()));
      

      输出:

      20 --> 20
      20 --> 20
      20,5 --> 20,5
      20,5 --> 20,5
      20,125 --> 20,125
      20,125 --> 20,125
      0 --> 0
      ==================
      20 --> 20
      20.00 --> 2
      20.5 --> 20.5
      20.5000 --> 20.5
      20.125 --> 20.125
      20.125000 --> 20.125
      0.000 --> 0
      

      【讨论】:

      • "20.00 --> 2" 我认为这不是好的行为。要修复它调用 TrimEnd 两次: TrimEnd('0'); TrimEnd(',');
      • 不要使用上面写的代码。 @VadymK 是正确的,它的行为是有缺陷的。如果没有句点,它将修剪句点之前的尾随零。
      【解决方案7】:

      我不认为这是开箱即用的,但是像这样的简单方法应该可以做到

      public static string TrimDecimal(decimal value)
      {
          string result = value.ToString(System.Globalization.CultureInfo.InvariantCulture);
          if (result.IndexOf('.') == -1)
              return result;
      
          return result.TrimEnd('0', '.');
      }
      

      【讨论】:

        【解决方案8】:

        开箱即用很容易:

        Decimal YourValue; //just as example   
        String YourString = YourValue.ToString().TrimEnd('0','.');
        

        这将从您的小数中删除所有尾随零。

        您唯一需要做的就是将.ToString().TrimEnd('0','.'); 添加到十进制变量中,以将Decimal 转换为不带尾随零的String,如上例所示。

        在某些地区,它应该是 .ToString().TrimEnd('0',',');(他们使用逗号而不是点,但您也可以添加点和逗号作为参数来确定)。

        (您也可以将两者都添加为参数)

        【讨论】:

        • gr8。现在你只剩下“0.0”了。将使用您的代码生成一个空字符串。
        • 那我建议调用 .ToString().TrimEnd('0').TrimEnd('.')。也代替“。”最好有 CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator 以便它跨文化工作。
        • @Mervin,请更改您的答案以反映 ΕГИІИО 的评论。您的代码会将50.0m 格式化为5,这显然是一个错误。
        • 投反对票。这会将 20 变成 2 :/
        【解决方案9】:
        decimal val = 0.000000000100m;
        string result = val == 0 ? "0" : val.ToString().TrimEnd('0').TrimEnd('.');
        

        【讨论】:

          【解决方案10】:

          如果您愿意按照the documentation 接受科学记数法,您可以使用G0 格式字符串:

          如果用科学计数法表示数字所产生的指数大于 -5 且小于精度说明符,则使用定点表示法;否则,使用科学计数法。

          您可以将此格式字符串用作.ToString() 方法的参数,或者将其指定为within an interpolated string。两者都如下所示。

          decimal input = 20.12500m;
          Console.WriteLine(input.ToString("G0")); // outputs 20.125
          Console.WriteLine($"{input:G0}"); // outputs 20.125
          
          decimal fourDecimalPlaces = 0.0001m;
          Console.WriteLine(fourDecimalPlaces.ToString("G0")); // outputs 0.0001
          Console.WriteLine($"{fourDecimalPlaces:G0}"); // outputs 0.0001
          
          decimal fiveDecimalPlaces = 0.00001m;
          Console.WriteLine(fiveDecimalPlaces.ToString("G0")); // outputs 1E-05
          Console.WriteLine($"{fiveDecimalPlaces:G0}"); // outputs 1E-05
          

          【讨论】:

            【解决方案11】:

            我最终得到了以下代码:

                public static string DropTrailingZeros(string test)
                {
                    if (test.Contains(CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator))
                    {
                        test = test.TrimEnd('0');
                    }
            
                    if (test.EndsWith(CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator))
                    {
                        test = test.Substring(0,
                            test.Length - CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator.Length);
                    }
            
                    return test;
                }
            

            【讨论】:

              【解决方案12】:

              我最终得到了这个变种:

              public static string Decimal2StringCompact(decimal value, int maxDigits)
                  {
                      if (maxDigits < 0) maxDigits = 0;
                      else if (maxDigits > 28) maxDigits = 28;
                      return Math.Round(value, maxDigits, MidpointRounding.ToEven).ToString("0.############################", CultureInfo.InvariantCulture);
                  }
              

              优点:

              您可以指定在运行时显示的点之后的最大有效位数;

              你可以显式指定一个round方法;

              您可以明确控制一种文化。

              【讨论】:

                【解决方案13】:

                你可以创建扩展方法

                public static class ExtensionMethod {
                  public static decimal simplify_decimal(this decimal value) => decimal.Parse($"{this:0.############}");
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-04-24
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多