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

C# 四舍五入到最佳单位而不损失精度,c#,vb.net,C#,Vb.net,我收到一个在“.”后面最多有4位的十进制数字,我知道这个数字是以毫克为单位的 我必须找到这个数字的最佳匹配单位(毫克、克、千克) 例如,如果我收到 已编辑 1160000.0000毫克,它将返回116.0000千克 66990000.0000毫克,它将返回66.9900千克 4900010.0000毫克,它将返回49000.0100克 49000000.0100毫克,它将返回49000000.0100毫克 1001毫克,它将返回1.0010克 1010毫克,它将返回1.0100克 1000毫克,

我收到一个在“.”后面最多有4位的十进制数字,我知道这个数字是以毫克为单位的

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

例如,如果我收到

已编辑

1160000.0000毫克,它将返回116.0000千克
66990000.0000毫克,它将返回66.9900千克
4900010.0000毫克,它将返回49000.0100克
49000000.0100毫克,它将返回49000000.0100毫克
1001毫克,它将返回1.0010克
1010毫克,它将返回1.0100克
1000毫克,它将返回0.0010千克
1100毫克,它将返回0.0011千克
135005毫克,它将返回135.0050克
最后一个样本是10013500毫克,它会返回10.0135公斤

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

Dim temp作为十进制
Dim u=新列表(整数)(新整数(){1,1000,1000000})
对于i=0到u,计数为-1
温度=CDec(数量/单位(i))
如果(temp*10000)-数学截断(temp*10000)为0,并且(temp*10000)-数学截断(temp*10000)<1,则
温度=CDec(数量/单位(i-1))
退出
如果结束
下一个
数量=温度
有更好/更好的方法来做我所做的事情吗

编辑以获得精度

输入可以是介于0.0001和.net中小数点可以接受的最大值之间的任何小数点


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

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

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");
}

你为什么不直接用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);

我不会在数字上做CStr,计算字符数,删除所有尾随的零,再次计算数字,并根据字符串中的字符数决定一个单位。然后,将原始数字除以正确的大小,再加上单位

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


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

您是不是最好实现或使用单元库进行转换,然后格式化结果

一些项目,虽然我不能保证任何项目的质量


java one讨论了

生成数字并选择合适的数字

    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;
    }
公共静态十进制格式十进制(十进制i)
{
List myFactors=新列表()
{1000m*1000m,1000m};
foreach(myFactors中的十进制转换因子)
{
十进制结果=十进制.四舍五入(i/转换系数,4);
如果(结果*转换因子==i)
{
返回结果;
}
}
返回i;
}

因此,如果我理解正确,任何带有分数0的参数ARG将保持原样,并以mg表示。。。这应该很容易编码

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

    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;
    }
在您的第一个示例中,我们从后端计算6个零,因此我们可以安全地除以10^(6+4),得到不超过4个小数位数(这比我们实际需要的多)

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

因此,如果“节省分割功率”大于等于6,则除以10^6并以kg表示 如果“保存除法功率”介于5和3之间,则除以10^3并以g表示,低于3则保留为mg


希望这会有所帮助。

我会失去精度,如果我通过1111111.1111,我只会看到1.11,其余的都在哪里?仍然在失去精度,我会看到1.1111,失去0.000011111,在有1111111111.1111的情况下,我必须显示1111111.1111毫格拉姆。对不起,我用更多的细节和例子再次更新了我的问题,我忘记了ll,我必须返回一个小数点,小数点后只有4位。“.为什么1001=g和1000=kg?4900010.0000=g和49000000.0100=mg?没有任何意义…1001毫克是1.0010克,1000毫克是0.0010克,4900010.0000毫克是49000.0100克,49000000.0100毫克已经四舍五入到最佳单位,即49000000.0100毫克。你可能也想看看。输入没有意义。前3个是整数,但最后一个有小数点?@Ian Quigley,我更新了我的问题,但仍然没有任何意义:1010=1.0100克,1000(小于1010)=0.0010公斤?祝你好运我觉得有趣的是,有六个人觉得这个问题足够好,可以花时间回答,但只有一个人投了赞成票。我会失去准确性,如果我通过1111111.1111,我只会看到1.11,其余的都在哪里?在除数的末尾加上一个D,使其成为一个双精度。1000D