4

我有一个 System.Decimal 数字

0.00123456789

我希望四舍五入到 3 位有效数字。我预计

0.00123

行为是舍入行为而不是截断。在.Net中是否有防弹方法可以做到这一点?

4

4 回答 4

5

你可以试试这个......但我不保证任何东西......在 20 分钟内编写和测试,并基于来自https://stackoverflow.com/a/1581007/613130的 Pyrolistical 的代码 有很大的不同,他变量使用a (long因为a的精度为15-16位,而a的精度为18-19,所以a就足够了),而我使用a (因为精度为28-29位)。shifteddoublelonglongdecimaldecimal

public static decimal RoundToSignificantFigures(decimal num, int n)
{
    if (num == 0)
    {
        return 0;
    }

    // We are only looking for the next power of 10... 
    // The double conversion could impact in some corner cases,
    // but I'm not able to construct them...
    int d = (int)Math.Ceiling(Math.Log10((double)Math.Abs(num)));
    int power = n - d;

    // Same here, Math.Pow(10, *) is an integer number
    decimal magnitude = (decimal)Math.Pow(10, power);

    // I'm using the MidpointRounding.AwayFromZero . I'm not sure
    // having a MidpointRounding.ToEven would be useful (is Banker's
    // rounding used for significant figures?)
    decimal shifted = Math.Round(num * magnitude, 0, MidpointRounding.AwayFromZero);
    decimal ret = shifted / magnitude;

    return ret;
}

如果你不相信(int)Math.Ceiling(Math.Log10((double)你可以使用这个:

private static readonly decimal[] Pows = Enumerable.Range(-28, 57)
    .Select(p => (decimal)Math.Pow(10, p))
    .ToArray();

public static int Log10Ceiling(decimal num)
{
    int log10 = Array.BinarySearch(Pows, num);
    return (log10 >= 0 ? log10 : ~log10) - 28;
}

我已经在另外 20 分钟内编写了它(是的,我已经测试了Math.Pow((double), p)所有值 -28 - +28 的所有值)。它似乎有效,并且仅比基于doubles) 的 C# 公式慢 20%。它基于 pow 的静态数组和BinarySearch. 幸运的是,BinarySearch当找不到下一个元素时,它已经“建议”了下一个元素:-),所以它Ceiling是免费的。

于 2013-08-09T11:52:01.317 回答
1

SqlDecimal 具有快速计算和调整精度的方法。

public static decimal RoundToSignificantFigures(decimal num, int n)
{
    SqlDecimal value = New SqlDecimal(num);
    if (value.Precision > num){
        int digits = num - (value.Precision - value.Scale);
        value = SqlDecimal.Round(value, digits);
        value = SqlDecimal.AdjustScale(value, (digits>0 ? digits : 0) - dstValue.Scale, True);
    }
    return value.Value;
}
于 2015-06-02T04:48:59.207 回答
0

例如:

decimal a = 1.9999M;
decimal b = Math.Round(a, 2); //returns 2
于 2013-08-09T10:27:51.937 回答
-1

尝试这个 ... decimalVar.ToString ("#.##");

于 2013-08-09T10:01:40.860 回答