【问题标题】:Truncate decimals beyond first positive截断除第一个正数之外的小数
【发布时间】:2014-04-14 07:09:48
【问题描述】:

C# - 截断除第一个正数之外的小数

号码是0.009012
结果应该是0.009

或者是1.1234 并且是1.1
2.099 ~ 2.09 等等

以快速和最佳的方式

【问题讨论】:

  • 你要显示这些值吗?还是用它们来计算?
  • 事实并非如此,我不赞成 Carra 提出的最短解决方案
  • 你想要它快,使用数学会比字符串解析更快。

标签: c# decimal truncate


【解决方案1】:

从数学上思考,使用以 10 为底的对数

这个函数只取第一个密码

public double RoundOnFirstDecimal(double number)
{
    int shift = -1 * ((int)Math.Floor(Math.Log10(number)));
    return Math.Floor(number * Math.Pow(10, shift)) / Math.Pow(10, shift);
}

但你想这样:(只会移动小数部分,而不是完整的数字)

public double RoundOnFirstDecimal(double number)
{
    int shift = -1 * ((int)Math.Floor(Math.Log10(number % 1)));
    return Math.Floor(number % 1 * Math.Pow(10, shift)) / Math.Pow(10, shift) + number - number % 1;
}

这将比任何正则表达式或循环快得多

【讨论】:

    【解决方案2】:

    试试这个方法:

    private static string RoundSpecial(double x)
    {
        string s = x.ToString();
        int dotPos = s.IndexOf('.');
        if (dotPos != -1)
        {
            int notZeroPos = s.IndexOfAny(new[] { '1', '2', '3', '4', '5', '6', '7', '8', '9' }, dotPos + 1);
            return notZeroPos == -1 ? s : s.Substring(0, notZeroPos + 1);
        }
        return s;
    }
    

    我不确定它是否是最快和最佳的方法,但它可以满足您的需求。

    第二种方法是使用Log10%

    private static double RoundSpecial(double x)
    {
        int pos = -(int)Math.Log10(x - (int)x);
        return Math.Round(x - (x % Math.Pow(0.1, pos + 1)), pos + 1);
    }
    

    【讨论】:

    • 解析为 double 是获取与您想要的位数不同的数字的好方法。
    • @Rawling 谢谢。解析已删除。还有其他问题吗?
    • 不!它与 OP 的示例相匹配,即使 OP 有一种奇怪的舍入方式:)
    【解决方案3】:

    你也可以试试正则表达式:

    decimal d = 2.0012m;            
    
    Regex pattern = new Regex(@"^(?<num>(0*[1-9]))\d*$");
    Match match = pattern.Match(d.ToString().Split('.')[1]);
    string afterDecimal = match.Groups["num"].Value; //afterDecimal = 001
    

    【讨论】:

      【解决方案4】:

      这是一个使用数学而不是字符串逻辑的解决方案:

      double nr = 0.009012;
      var partAfterDecimal = nr - (int) nr;
      var partBeforeDecimal = (int) nr;
      
      int count = 1;
      partAfterDecimal*=10;
      int number = (int)(partAfterDecimal);
      while(number == 0)
      {
        partAfterDecimal *= 10;
        number = (int)(partAfterDecimal);
        count++;
      }
      
      double dNumber = number;
      while(count > 0){
       dNumber /= 10.0;
       count--;
      }
      
      double result = (double)partBeforeDecimal + dNumber;
      result.Dump();
      

      【讨论】:

        【解决方案5】:

        如果您不想使用Math 库:

            static double truncateMyWay(double x)
            {
                double afterDecimalPoint = x - (int)x;
                if (afterDecimalPoint == 0.0) return x;
                else
                {
                    int i = 0;
                    int count10 = 1;
                    do 
                    {
                        afterDecimalPoint *= 10;
                        count10 *= 10;
                        i++;
                    } while ((int) afterDecimalPoint == 0);
        
                    return ((int)(x * count10))/((double)count10);
                }
            }
        

        编码愉快! ;-)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-05
          • 2022-10-23
          相关资源
          最近更新 更多