如何在.net舍System.Decimal到若干显著数字 [英] How to round System.Decimal in .Net to a number of significant figures
问题描述
我有一个System.Decimal数字
I have a System.Decimal number
0.00123456789
0.00123456789
,我希望舍入为3个有效数字中。我期望
and I wish to round to 3 significant figures. I expect
0.00123
,其行为是舍入行为,而不是截断。
with the behaviour to be a rounding behaviour rather than truncation. Is there a bullet proof way to do this in .Net?
推荐答案
你可以试试这个...但我不是保证任何...在20分钟内编写和测试,基于Pyrolistical的代码,来自 http://stackoverflow.com/a/1581007/613130有一个很大的区别,他使用 long
为移位
变量因为 double
的精度为15-16位数,而 long
有18-19,因此 long
就足够了),而我使用 decimal
(因为具有28-29位数的精度。)
You can try this... But I don't guarantee anything... Written and tested in 20 minutes and based on Pyrolistical's code from http://stackoverflow.com/a/1581007/613130
There is a big difference in that he uses a long
for the shifted
variable (because a double
has a precision of 15-16 digits, while a long
has 18-19, so a long
is enough), while I use a decimal
(because decimal
has a precision of 28-29 digits).
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 num >= 0 ? ret : -ret;
}
如果不信任 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)。似乎工作,它只有20%基于 double
s的C#公式,它基于pows的静态数组和 BinarySearch
。幸运的是, code> BinarySearch 已经建议下一个元素,当它找不到一个:-),因此 Ceiling
是免费的。
I have written it in another 20 minutes (and yes, I have tested all the Math.Pow((double), p)
for all the values -28 - +28). It seems to work, and it's only 20% slower than the C# formula based on double
s). It's based on a static array of pows and a BinarySearch
. Luckily the BinarySearch
already "suggests" the next element when it can't find one :-), so the Ceiling
is for free.
这篇关于如何在.net舍System.Decimal到若干显著数字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!