0

この小さなコンソール アプリケーションは BigInteger をカウントし、ヒットした指数をフィードバックします。

今、私はいくつかの速度の改善に興味があります。私に何ができる?

あなたの提案をありがとう!

using System;
using System.Collections.Generic;
using System.Numerics;

namespace Counter
{
    internal class Program
    {
        private static readonly Dictionary<BigInteger, int> Dic = new Dictionary<BigInteger, int>();

        private static void Main(string[] args)
        {
            Console.WriteLine("Start with counting ... from 1 to 2^256.");
            Console.WriteLine();

            CreateDict();

            var bigInteger = new BigInteger();

            Console.WriteLine("D:HH:mm:ss,ms      - fac.  - Number");
            Console.WriteLine("---------------------------------------------------");

            var startTime = DateTime.UtcNow;
            while (true)
            {
                bigInteger++;
                if (Dic.ContainsKey(bigInteger))
                {
                    Console.WriteLine("{0:G} - 2^{1,3} = {2:#,0}", (DateTime.UtcNow - startTime), Dic[bigInteger], bigInteger);
                }
            }
        }

        private static void CreateDict()
        {
            for (int i = 1; i <= 256; i++)
            {
                Dic.Add(BigInteger.Pow(2, i), i);
            }
        }
    }
}

出力: http://pastebin.com/bMBntFsL

進捗

BigInteger での作業はあまり良くありませんでした。

BigInteger 2^26 = 5 秒

ダブル 2^26 = 1,3 秒

Dict から直接比較への切り替えは、

            int i = 1;
            double pow = Math.Pow(2, i);
            while (true)
            {
                bigInteger++;
                if (bigInteger == pow)
                {
                    Console.WriteLine("{0:G} - 2^{1,3} = {2:#,0}", (DateTime.UtcNow - startTime), Dic[bigInteger], bigInteger);

                    i++;
                    pow = Math.Pow(2, i);
                }
            }

辞書 2^26 = 1,3 秒

"<" 2^26 = 0,5 秒

4

1 に答える 1

2

ループで 2^256 までカウントしたい場合は、 を使用しないでくださいBigInteger

MSDNから:

.NET Framework の他の数値型も不変です。ただし、BigInteger 型には上限または下限がないため、その値が非常に大きくなり、パフォーマンスに測定可能な影響を与える可能性があります。

このプロセスは呼び出し元には透過的ですが、パフォーマンスが低下します。場合によっては、特に非常に大きな BigInteger 値のループで繰り返し操作が実行される場合、そのパフォーマンスのペナルティが重大になる可能性があります。

目的の値は大きいですが、信じられないほど大きいわけではないため、代わりに a を使用できますdoubledouble値は まで上がる可能性が1.7 × 10^308あるため、2^256 (つまり1.15 × 10^77) で問題ありません。これは、アプリケーションのパフォーマンスに大いに役立つはずです。


この回答でわかるように、他の改善点は、TryGetValueの代わりに辞書に使用することです。ContainsKey

両方ContainsKey(bigInteger)Dic[bigInteger]行っており、ルックアップを 2 回行っているためです。

したがって、コードは次のようになります。

while (true)
{
    bigValue++;

    int exponent;
    if (Dic.TryGetValue(bigValue, out exponent))
    {
        Console.WriteLine("{0:G} - 2^{1,3} = {2:#,0}", (DateTime.UtcNow - startTime), exponent, bigValue);
    }
}
于 2013-10-02T14:06:09.173 に答える