使用尾随零生成小数

时间:2017-12-15 18:31:24

标签: c#

我需要将小数舍入到特定数量的有效数字。我有一个可以简化的库。

decimal a = Math.Round(20.051M * 100M) / 100M; // 20.05
decimal b = Math.Round(20.001M * 100M) / 100M; // 20;

显然我在执行Round时丢失了尾随的零,我可以通过添加.00M来恢复它们。有没有办法动态地执行此操作,如果我要四舍五入到我想要的五个重要数字使用.000M,同样如果我的小数是< 10 .000M是合适的。

b = b + .00M; // 20.00

这里参考的是实际的舍入方法。

DecimalExtensions.cs

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

/// <remarks>https://stackoverflow.com/a/18146056/3194005</remarks>
public static decimal RoundToSignificantFigures(this decimal value, int significantFigures)
{
    if (value == 0)
        return 0;

    int d = Log10Ceiling(Math.Abs(value));
    int power = significantFigures - d;

    decimal magnitude = (decimal)Math.Pow(10, power);

    return Math.Round(value * magnitude) / magnitude;
}

private static int Log10Ceiling(decimal value)
{
    int log10 = Array.BinarySearch(Pows, value);

    return (log10 >= 0 ? log10 : ~log10) - 28;
}

3 个答案:

答案 0 :(得分:1)

您可以通过计算mag -1 的值并从其自身减去它来使用小数点后所需的零数来创建一个值:

var res = Math.Round(value * magnitude) / magnitude;
var invMag = 1/magnitude;
return res + invMag - invMag;

在您的示例中,mag = 10 2 ,因此invMag = 10 -2 或0.01。当你减去0.01M - 0.01M时,你会得到0.00M,你可以将其添加到结果中,以强制它拥有所需数量的尾随零而不更改值。

Demo

答案 1 :(得分:1)

这不是答案,评论太长,而且对于新问题来说太具体了,所以......

我在这里问similar question,发现了一个异常,dotnetfiddle compiler为你的例子返回20:

decimal b = Math.Round(20.001M * 100M) / 100M; 
b = b + .00M; 

然而它(正确地)返回20.00表示:

decimal b = Math.Round(20.001M * 100M) / 100M; 
b = Decimal.Add(b, .00M);

使用我尝试过的Visual Studio编译器(VS2013,VS2015)返回20.00。

我不知道这是否是编译错误,但在没有解释的情况下我更喜欢第二版。

答案 2 :(得分:-1)

20M的值与20.00M相同,如果它的格式仅为用户

Meta

Checkout NumberFormatInfo - https://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo(v=vs.110).aspx