Вычислите систему. Десятичная точность и масштаб

Вы должны использовать try catch в этом коде

getFriendsPosts = async (user,callback) => {
    const arr = [];
    const array = [];
    const db = await MongoClient.connect(url);
    const dbo = db.db("drone-x");
    const results = await dbo.collection("users").find({_id: ObjectId(user.id)})
    const resultPromise =  _.map(results, async element => {
        const friends = _.get(element, 'friends', [])
        if(friends.length != 0) {
        const friendPromise =  _.map(friends, async friend => {
            const ress = await dbo.collection("users").find({_id: ObjectId(friend.id)})
            arr.push(ress);
            const resPromise = _.map(ress, async res => {
             const posts = await dbo.collection("posts").find({userId: res._id.toString()})
                const postPromise =  _.map(posts, post => {
                    array.push(post);
                })
              await Promise.all(postPromise)
            })
           await Promise.all(resPromise)
        })
       await Promise.all(friendPromise)
        } 
    })
   await Promise.all(resultPromise)
    return { arr , array }
}

Я не рекомендую, чтобы это занимало слишком много времени. Вы должны использовать мангуста и использовать агрегацию для длинных запросов.

23
задан Jason Kresowaty 18 April 2009 в 18:52
поделиться

2 ответа

Да, вам нужно использовать Decimal.GetBits . К сожалению, вам придется работать с 96-разрядным целым числом, и в .NET нет простого целочисленного типа, который бы справлялся с 96-разрядным. С другой стороны, возможно, что вы могли бы использовать Decimal сам ...

Вот некоторый код, который выдает те же числа, что и ваши примеры. Надеюсь, вы найдете это полезным:)

using System;

public class Test
{
    static public void Main(string[] x)
    {
        ShowInfo(123.4500m);
        ShowInfo(0m);
        ShowInfo(0.0m);
        ShowInfo(12.45m);
        ShowInfo(12.4500m);
        ShowInfo(770m);
    }

    static void ShowInfo(decimal dec)
    {
        // We want the integer parts as uint
        // C# doesn't permit int[] to uint[] conversion,
        // but .NET does. This is somewhat evil...
        uint[] bits = (uint[])(object)decimal.GetBits(dec);


        decimal mantissa = 
            (bits[2] * 4294967296m * 4294967296m) +
            (bits[1] * 4294967296m) +
            bits[0];

        uint scale = (bits[3] >> 16) & 31;

        // Precision: number of times we can divide
        // by 10 before we get to 0        
        uint precision = 0;
        if (dec != 0m)
        {
            for (decimal tmp = mantissa; tmp >= 1; tmp /= 10)
            {
                precision++;
            }
        }
        else
        {
            // Handle zero differently. It's odd.
            precision = scale + 1;
        }

        uint trailingZeros = 0;
        for (decimal tmp = mantissa;
             tmp % 10m == 0 && trailingZeros < scale;
             tmp /= 10)
        {
            trailingZeros++;
        }

        Console.WriteLine("Example: {0}", dec);
        Console.WriteLine("Precision: {0}", precision);
        Console.WriteLine("Scale: {0}", scale);
        Console.WriteLine("EffectivePrecision: {0}",
                          precision - trailingZeros);
        Console.WriteLine("EffectiveScale: {0}", scale - trailingZeros);
        Console.WriteLine();
    }
}
27
ответ дан 29 November 2019 в 01:08
поделиться

Использование ToString примерно в 10 раз быстрее, чем решение Джона Скита. Несмотря на то, что это достаточно быстро, задача здесь (если есть кто-нибудь!) Состоит в том, чтобы побить производительность ToString.

Результаты производительности, которые я получаю от следующей тестовой программы: ShowInfo 239 мс FastInfo 25 мс

using System;
using System.Diagnostics;
using System.Globalization;

public class Test
{
    static public void Main(string[] x)
    {
        Stopwatch sw1 = new Stopwatch();
        Stopwatch sw2 = new Stopwatch();

        sw1.Start();
        for (int i = 0; i < 10000; i++)
        {
            ShowInfo(123.4500m);
            ShowInfo(0m);
            ShowInfo(0.0m);
            ShowInfo(12.45m);
            ShowInfo(12.4500m);
            ShowInfo(770m);
        }
        sw1.Stop();

        sw2.Start();
        for (int i = 0; i < 10000; i++)
        {
            FastInfo(123.4500m);
            FastInfo(0m);
            FastInfo(0.0m);
            FastInfo(12.45m);
            FastInfo(12.4500m);
            FastInfo(770m);
        }
        sw2.Stop();

        Console.WriteLine(sw1.ElapsedMilliseconds);
        Console.WriteLine(sw2.ElapsedMilliseconds);
        Console.ReadLine();
    }

    // Be aware of how this method handles edge cases.
    // A few are counterintuitive, like the 0.0 case.
    // Also note that the goal is to report a precision
    // and scale that can be used to store the number in
    // an SQL DECIMAL type, so this does not correspond to
    // how precision and scale are defined for scientific
    // notation. The minimal precision SQL decimal can
    // be calculated by subtracting TrailingZeros as follows:
    // DECIMAL(Precision - TrailingZeros, Scale - TrailingZeros).
    //
    //     dec Precision Scale TrailingZeros
    // ------- --------- ----- -------------
    //   0             1     0             0
    // 0.0             2     1             1
    // 0.1             1     1             0
    // 0.01            2     2             0 [Diff result than ShowInfo]
    // 0.010           3     3             1 [Diff result than ShowInfo]
    // 12.45           4     2             0
    // 12.4500         6     4             2
    // 770             3     0             0
    static DecimalInfo FastInfo(decimal dec)
    {
        string s = dec.ToString(CultureInfo.InvariantCulture);

        int precision = 0;
        int scale = 0;
        int trailingZeros = 0;
        bool inFraction = false;
        bool nonZeroSeen = false;

        foreach (char c in s)
        {
            if (inFraction)
            {
                if (c == '0')
                    trailingZeros++;
                else
                {
                    nonZeroSeen = true;
                    trailingZeros = 0;
                }

                precision++;
                scale++;
            }
            else
            {
                if (c == '.')
                {
                    inFraction = true;
                }
                else if (c != '-')
                {
                    if (c != '0' || nonZeroSeen)
                    {
                        nonZeroSeen = true;
                        precision++;
                    }
                }
            }
        }

        // Handles cases where all digits are zeros.
        if (!nonZeroSeen)
            precision += 1;

        return new DecimalInfo(precision, scale, trailingZeros);
    }

    struct DecimalInfo
    {
        public int Precision { get; private set; }
        public int Scale { get; private set; }
        public int TrailingZeros { get; private set; }

        public DecimalInfo(int precision, int scale, int trailingZeros)
            : this()
        {
            Precision = precision;
            Scale = scale;
            TrailingZeros = trailingZeros;
        }
    }

    static DecimalInfo ShowInfo(decimal dec)
    {
        // We want the integer parts as uint
        // C# doesn't permit int[] to uint[] conversion,
        // but .NET does. This is somewhat evil...
        uint[] bits = (uint[])(object)decimal.GetBits(dec);


        decimal mantissa =
            (bits[2] * 4294967296m * 4294967296m) +
            (bits[1] * 4294967296m) +
            bits[0];

        uint scale = (bits[3] >> 16) & 31;

        // Precision: number of times we can divide
        // by 10 before we get to 0 
        uint precision = 0;
        if (dec != 0m)
        {
            for (decimal tmp = mantissa; tmp >= 1; tmp /= 10)
            {
                precision++;
            }
        }
        else
        {
            // Handle zero differently. It's odd.
            precision = scale + 1;
        }

        uint trailingZeros = 0;
        for (decimal tmp = mantissa;
            tmp % 10m == 0 && trailingZeros < scale;
            tmp /= 10)
        {
            trailingZeros++;
        }

        return new DecimalInfo((int)precision, (int)scale, (int)trailingZeros);
    }
}
11
ответ дан 29 November 2019 в 01:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: