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