有没有办法让"显著数字"的小数? [英] Is there a way to get the "significant figures" of a decimal?

查看:176
本文介绍了有没有办法让"显著数字"的小数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

确定,经过一番调查,并在很大一部分要归功于乔恩和汉斯提供了有益的答案,这就是我能够放在一起。到目前为止,我觉得它似乎运作良好。我不会赌当然,我的生活就其总的正确性。

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆