我需要将小数舍入到特定数量的有效数字。我有一个可以简化的库。
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;
}
答案 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
,你可以将其添加到结果中,以强制它拥有所需数量的尾随零而不更改值。
答案 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