如何将.Net中的System.Decimal舍入到一些重要数字中
我有一个System.Decimal数字
0.00123456789
我希望得到3位重要数字。 我预计
0.00123
行为是舍入行为而不是截断。 在.Net中是否有防弹方法可以做到这一点?
你可以尝试这个…但我不保证任何事情……在20分钟内编写并测试并根据来自https://stackoverflow.com/a/1581007/613130的 Pyrolistical代码有一个很大的不同之处在于他对shifted
变量使用long
(因为double
的精度为15-16位,而long
有18-19,所以long
就足够了),而我使用decimal
(因为decimal
的精度为28-29)位)。
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分钟内写了它(是的,我已经测试了所有数值-28 – +28)的所有Math.Pow((double), p)
)。 它似乎工作,并且它比基于double
s的C#公式慢20%。 它基于静态的pows数组和BinarySearch
。 幸运的是BinarySearch
已经“建议”下一个元素,当它找不到一个:-)时,所以Ceiling
是免费的。
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; }
试试这个…… decimalVar.ToString ("#.##");
在示例中:
decimal a = 1.9999M; decimal b = Math.Round(a, 2); //returns 2