更新
好的,经过一番调查,在很大程度上要感谢 Jon 和 Hans 提供的有用答案,这就是我能够整理出来的。到目前为止,我认为它似乎运作良好。当然,我不会赌它的完全正确性。
public static int GetSignificantDigitCount(this decimal value)
{
/* So, the decimal type is basically represented as a fraction of two
* integers: a numerator that can be anything, and a denominator that is
* some power of 10.
*
* For example, the following numbers are represented by
* the corresponding fractions:
*
* VALUE NUMERATOR DENOMINATOR
* 1 1 1
* 1.0 10 10
* 1.012 1012 1000
* 0.04 4 100
* 12.01 1201 100
*
* So basically, if the magnitude is greater than or equal to one,
* the number of digits is the number of digits in the numerator.
* If it's less than one, the number of digits is the number of digits
* in the denominator.
*/
int[] bits = decimal.GetBits(value);
if (value >= 1M || value <= -1M)
{
int highPart = bits[2];
int middlePart = bits[1];
int lowPart = bits[0];
decimal num = new decimal(lowPart, middlePart, highPart, false, 0);
int exponent = (int)Math.Ceiling(Math.Log10((double)num));
return exponent;
}
else
{
int scalePart = bits[3];
// Accoring to MSDN, the exponent is represented by
// bits 16-23 (the 2nd word):
// http://msdn.microsoft.com/en-us/library/system.decimal.getbits.aspx
int exponent = (scalePart & 0x00FF0000) >> 16;
return exponent + 1;
}
}
我还没有彻底测试它。不过,这里有一些示例输入/输出:
价值精度 0 1 位数。 0.000 4 位数。 1.23 3 位数。 12.324 5 位数。 1.2300 5 位数。 -5 1 位数。 -5.01 3 位数。 -0.012 4 位数。 -0.100 4 位数。 0.0 2 位数。 10443.31 7 位数。 -130.340 6 位数。 -80.8000 6 位数。
使用此代码,我想我会通过执行以下操作来实现我的目标:
public static decimal DivideUsingLesserPrecision(decimal x, decimal y)
{
int xDigitCount = x.GetSignificantDigitCount();
int yDigitCount = y.GetSignificantDigitCount();
int lesserPrecision = System.Math.Min(xDigitCount, yDigitCount);
return System.Math.Round(x / y, lesserPrecision);
}
不过,我还没有真正完成这个工作。任何想分享想法的人:将不胜感激!
原始问题
假设我写了这段代码:
decimal a = 1.23M;
decimal b = 1.23000M;
Console.WriteLine(a);
Console.WriteLine(b);
以上将输出:
1.23 1.23000
我发现如果我使用decimal.Parse("1.23")
fora
和decimal.Parse("1.23000")
for这也有效b
(这意味着这个问题适用于程序接收用户输入的情况)。
很明显,一个decimal
值以某种方式“意识到”了我所说的精度。decimal
但是,除了ToString
自身之外,我没有看到该类型的成员提供任何访问方式。
假设我想将两个decimal
值相乘并将结果修剪到不太精确的参数的精度。换句话说:
decimal a = 123.4M;
decimal b = 5.6789M;
decimal x = a / b;
Console.WriteLine(x);
上述输出:
21.729560302171195125816619416
我要问的是:我怎么能写一个返回的方法21.73
(因为123.4M
有四个有效数字)?
明确一点:我意识到我可以调用ToString
这两个参数,计算每个字符串中的有效数字,并使用这个数字对计算结果进行四舍五入。如果可能的话,我正在寻找一种不同的方式。
(我也意识到,在您处理有效数字的大多数情况下,您可能不需要使用该decimal
类型。但我问是因为,正如我在开头提到的那样,该decimal
类型似乎包含有关精度,而double
据我所知没有。)