代码之家  ›  专栏  ›  技术社区  ›  Fredou

四舍五入到最佳单位而不损失精度

  •  1
  • Fredou  · 技术社区  · 16 年前

    我必须找到这个数字的最佳匹配单位(毫克、克、千克)。

    例如,如果我收到

    编辑

    1160000.0000毫克,它将返回116.0000公斤
    66990000.0000毫克,它将返回66.9900公斤
    4900010.0000毫克,它将返回49000.0100克

    1001毫克,它会返回1.0010克

    1000毫克,它会返回0.0010公斤
    1100毫克,它会返回0.0011公斤

    我目前正在使用这个代码, 我认为这看起来很难看,可能会失败

    Dim temp As Decimal
    Dim u = New List(Of Integer)(New Integer() {1, 1000, 1000000})
    For i = 0 To u.Count - 1
        temp = CDec(qty / u(i))
        If (temp * 10000) - Math.Truncate(temp * 10000) <> 0 AndAlso (temp * 10000) - Math.Truncate(temp * 10000) < 1 Then
            temp = CDec(qty / u(i - 1))
            Exit For
        End If
    Next
    qty = temp
    

    有更好/更好的方法来做我所做的事情吗?

    精确编辑

    输出需要四舍五入到最佳单位,在“.”之后最多有4位数字,且不损失任何精度

    6 回复  |  直到 16 年前
        1
  •  3
  •   Amy B    16 年前

    生成数字并选择合适的一个。

        public static decimal FormatDecimal(decimal i)
        {
            decimal milli = i;
            decimal grams = decimal.Round(i / 1000m, 4);
            decimal kilo = decimal.Round(grams / 1000m, 4);
    
            if (kilo * 1000 * 1000 == milli)
            {
                return kilo;
            }
            if (grams * 1000 == milli)
            {
                return grams;
            }
            return milli;
        }
    

    并测试:

        public static void FormatDecimalTest()
        {
            if (FormatDecimal(116000000.0000m) == 116.0000m)
                Console.WriteLine("ok1");
            if (FormatDecimal(66990000.0000m) == 66.9900m)
                Console.WriteLine("ok2");
            if (FormatDecimal(49000010.0000m) == 49000.0100m)
                Console.WriteLine("ok3");
            if (FormatDecimal(49000000.0100m) == 49000000.0100m)
                Console.WriteLine("ok4");
            if (FormatDecimal(1001m) == 1.0010m)
                Console.WriteLine("ok5");
            if (FormatDecimal(1000m) == 0.0010m)
                Console.WriteLine("ok6");
            if (FormatDecimal(1100m) == 0.0011m)
                Console.WriteLine("ok7");
            if (FormatDecimal(1100m) == 0.0011m)
                Console.WriteLine("ok8");
            if (FormatDecimal(135005m) == 135.0050m)
                Console.WriteLine("ok9");
            if (FormatDecimal(10013500m) == 10.0135m)
                Console.WriteLine("ok10");
        }
    

    在你的问题中,我看到你对各种因素进行了循环。这里有一个循环解决方案,它将找到第一个不会失去精度的因素。

        public static decimal FormatDecimal(decimal i)
        {
            List<decimal> myFactors = new List<decimal>()
            { 1000m * 1000m, 1000m};
    
            foreach (decimal conversionFactor in myFactors)
            {
                decimal result = decimal.Round(i / conversionFactor, 4);
                if (result * conversionFactor == i)
                {
                    return result;
                }
            }
    
            return i;
        }
    
        2
  •  0
  •   hackerhasid    16 年前

    你为什么不直接用ifs呢?比如:

    if (num > 1000000) 
    return string.format("{0.####} kg", num/1000000)
    
    if (num > 1000) 
    return string.format("{0.####} g", num/1000);
    
    return string.format("{0.####} mg", num);
    
        3
  •  0
  •   iandisme    16 年前

    但是,在执行此操作之前,您需要对原始值进行截断,并查看返回的值是否与原始值匹配;那你就用mg。

    可能不会比您的代码工作得更好,但它可能更易于阅读。大概

        4
  •  0
  •   Rubens Farias    16 年前

    您的示例没有太多意义,但您应该使用以下内容:

    static string FormatWeight(double value)
    {
        if (value > 10000000) return (value / 10000000D).ToString("0.#### t");
        if (value > 100000) return (value / 100000D).ToString("0.#### kg");
        if (value > 1000) return (value / 1000D).ToString("0.#### g");
        return value.ToString("0.#### mg");
    }
    
        5
  •  0
  •   Community Mohan Dere    9 年前

    一些项目 here here ,虽然我不能保证它的质量。。。

    讨论了java 1 here

        6
  •  0
  •   MikeD    16 年前

    如果我理解正确,任何带分数的参数ARG<&燃气轮机;0将保持原样并以mg表示。。。这应该很容易编码

    If ARG <> Int(ARG) Then
       ' Return ARG
    Endif
    

    任何没有分数的东西都应转换为最合适的单位(mg、g、dag、kg、t等)。因此,对于这些,我们需要将参数视为一个字符串,并从后端计算“0”个数,并从中了解在不降低数值精度的情况下,我们可以除以10的频率。

    在您的上一个示例中,我们从后面数2“0”es,因此我们可以安全地除以10^(2+4)。

    如果“保存除法功率”介于5和3之间,则除以10^3并以g表示,低于3则保留为mg。

    希望有帮助。