سؤال

التحديث

حسنا, بعد بعض التحقيقات ، ويرجع الفضل في جزء كبير إلى الإجابات المفيدة التي قدمها جون هانز, هذا ما كنت قادرة على وضع معا.حتى الآن أعتقد أنه يبدو للعمل بشكل جيد.أنا لا أراهن بحياتي على مجموع صحة بالطبع.

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.cimal بتتبع عدد الأرقام في الحرفي. هذه ميزة من Decimal.parse () ، سواء تم تنفيذها بواسطة الكود بنفسك أو بواسطة المترجم عندما يتوصل إلى حرفي في البرنامج. يمكنك استرداد هذه المعلومات ، والتحقق من الكود في إجابتي في هذا الموضوع.

إن استرداد عدد الأرقام المهمة بعد القيام بالرياضيات على القيمة يضربني كقطعة طويلة. لا فكرة عما إذا كان المشغلون يحافظون عليهم ، يرجى إعلامنا بما تكتشفه.

الحل أعلاه يسقط من السرير بسرعة مع القيم مثل 1200 حيث عدد ارقام كبيرة 2 ولكن ترجع الدالة 4.ربما هناك بطريقة متسقة للتعامل مع مثل هذه الحالة أيتأكد من إرجاع القيمة لا تشمل زائدة الأصفار في كل جزء دون جزء كسري.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top