有没有办法让"显著数字"的小数? [英] Is there a way to get the "significant figures" of a decimal?
问题描述
确定,经过一番调查,并在很大一部分要归功于乔恩和汉斯提供了有益的答案,这就是我能够放在一起。到目前为止,我觉得它似乎运作良好。我不会赌当然,我的生活就其总的正确性。
OK, after some investigation, and thanks in big part to the helpful answers provided by Jon and Hans, this is what I was able to put together. So far I think it seems to work well. I wouldn't bet my life on its total correctness, of course.
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;
}
}
我还没有彻底测试这一切。这里有一些样品输入/输出,但:
I haven't tested it all that thoroughly. Here are a few sample inputs/outputs, though:
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).
使用这个code,我想我会实现我的目标做这样的事情:
Using this code, I imagine I would accomplish my goal by doing something like this:
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);
}
我还没有真正完成过这样的工作,虽然。如果谁想要分享的想法:那会是多少AP preciated
I haven't really finished working through this, though. Anybody who wants to share thoughts: that would be much appreciated!
假设我有写这篇code:
Suppose I have write this code:
decimal a = 1.23M;
decimal b = 1.23000M;
Console.WriteLine(a);
Console.WriteLine(b);
以上将输出:
The above will output:
1.23
1.23000
我觉得这也适用,如果我用 decimal.Parse(1.23)
为 A
和 decimal.Parse(1.23000)
为 B
(这意味着这个问题适用于在节目接收用户输入的情况下)
I find that this also works if I use decimal.Parse("1.23")
for a
and decimal.Parse("1.23000")
for b
(which means this question applies to cases where the program receives user input).
所以显然十进制
值为某种方式知道什么,我会打电话给它的 precision 的。但是,我看到了十进制没有成员
键入提供任何访问该的,除了的ToString
本身。
So clearly a decimal
value is somehow "aware" of what I'll call its precision. However, I see no members on the decimal
type that provide any way of accessing this, aside from ToString
itself.
假设我想将两个十进制
值和修剪的结果不太precise参数的precision。换句话说:
Suppose I wanted to multiply two decimal
values and trim the result to the precision of the less precise argument. In other words:
decimal a = 123.4M;
decimal b = 5.6789M;
decimal x = a / b;
Console.WriteLine(x);
以上输出:
21.729560302171195125816619416
我要问的是:我怎么会写一个方法,将返回 21.73
,而不是(因为 123.4M
有四个显著数字)?
What I'm asking is: how could I write a method that would return 21.73
instead (since 123.4M
has four significant figures)?
需要明确的是:我知道我可以叫的ToString
的两个参数,每个字符串中算显著的数字,并用这个号圆计算的结果。我在寻找一个的不同的的方式,如果可能的话。
To be clear: I realize I could call ToString
on both arguments, count the significant figures in each string, and use this number to round the result of the calculation. I'm looking for a different way, if possible.
(我的也的实现,在大多数情况下,您正在处理显著的数字,你可能并不需要使用的十进制
类型。但是,我这么问是因为,正如我在一开始提到的,十进制
键入显示的,包括约precision信息,而双
没有,据我所知。)
(I also realize that in most scenarios where you're dealing with significant figures, you probably don't need to be using the decimal
type. But I'm asking because, as I mentioned in the beginning, the decimal
type appears to include information about precision, whereas double
does not, as far as I know.)
推荐答案
您可以使用的 Decimal.GetBits
,以获得原始数据,并从工作了。
You can use Decimal.GetBits
to get the raw data, and work it out from that.
不幸的是我没有时间在此刻写样本code - 你可能会想使用的 的BigInteger
的一些操作,如果您使用的是.NET 4 - 但希望这将让你去。刚参加工作了precision,然后调用 Math.Round
上的原始结果很可能是一个良好的开端。
Unfortunately I don't have time to write sample code at the moment - and you'll probably want to use BigInteger
for some of the manipulation, if you're using .NET 4 - but hopefully this will get you going. Just working out the precision and then calling Math.Round
on the original result may well be a good start.
这篇关于有没有办法让&QUOT;显著数字&QUOT;的小数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!