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 并不是那么好。

大整数 2^26 = 5s

双 2^26 = 1,3s

从 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,3s

"<" 2^26 = 0,5s

4

1 回答 1

2

如果您真的想在一个循环中最多计数 2^256,请不要使用BigInteger.

来自MSDN

.NET Framework 中的其他数字类型也是不可变的。但是,由于 BigInteger 类型没有上限或下限,它的值可能会变得非常大,并对性能产生可衡量的影响。

尽管此过程对调用者是透明的,但它确实会导致性能损失。在某些情况下,尤其是在循环中对非常大的 BigInteger 值执行重复操作时,性能损失可能很大

由于您想要的值很大但不是非常大,您可以使用 adouble代替。double值可以上升到1.7 × 10^308,所以你可以使用 2^256 (即1.15 × 10^77)。这应该对您的应用程序的性能有很大帮助。


正如您在此答案中看到的那样,另一个改进是使用TryGetValue您的字典而不是。ContainsKey

因为你正在做这两个ContainsKey(bigInteger)Dic[bigInteger]你正在做两次查找。

所以代码会变成:

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 回答