有没有办法获得小数的“重要人物”?
-
02-10-2019 - |
题
更新
好的,经过一番调查,并感谢乔恩和汉斯提供的有用答案,这就是我能够组合在一起的。到目前为止,我认为它似乎运行良好。当然,我不会押注我的生活。
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;
}
}
我还没有对所有测试进行彻底测试。但是,这是一些样本输入/输出:
Value Precision 0 1 digit(s). 0.000 4 digit(s). 1.23 3 digit(s). 12.324 5 digit(s). 1.2300 5 digit(s). -5 1 digit(s). -5.01 3 digit(s). -0.012 4 digit(s). -0.100 4 digit(s). 0.0 2 digit(s). 10443.31 7 digit(s). -130.340 6 digit(s). -80.8000 6 digit(s).
使用此代码,我想我会通过这样的事情来实现我的目标:
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")
为了 a
和 decimal.Parse("1.23000")
为了 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
据我所知,没有。)
解决方案
您可以使用 Decimal.GetBits
获取原始数据,并从中解决。
不幸的是,我目前没有时间编写示例代码 - 您可能想使用 BigInteger
对于某些操作,如果您使用的是.NET 4-但希望这会让您前进。只是锻炼精度然后打电话 Math.Round
最初的结果很可能是一个很好的开始。
其他提示
是的,与浮点类型不同,System.DECIMAL跟踪文字中的数字数量。这是DECIMAL.PARSE()的功能,无论是您自己执行的代码还是在编译器中解析您的程序中的文字时。您可以恢复此信息,在我的答案中查看代码 这个线程.
在您进行数学数量之后,恢复了大量数字的数量,这使我长期以赴。不知道操作员是否保留它们,请让我们知道您发现的内容。
上方的解决方案以1200之类的值迅速从床上掉下来,其中有效数字的数量为2,但功能返回4.也许有一种一致的方式处理这种情况,即确保返回值不包括尾随Zeros在整个数字中,没有分数部分。