具有Biginteger计算的控制台应用程序冻结

时间:2017-11-25 11:40:28

标签: c# visual-studio console-application primes freeze

问题

具有Biginteger计算的控制台应用程序冻结

详细

我正在用C#开发一个控制台应用程序,它测试非常大的数字(10到几十到几百的幂)是否为素数。由于默认整数类型只能处理最多10 ^ 19(longulong)的数字,因此我使用BitInteger类。但是当我在Visual Studio中以调试模式运行应用程序时,应用程序会冻结。

    static void Main(string[] args)
    {
        int exp = 100;
        var bi = BigInteger.Pow(10, exp);
        var sw = new Stopwatch();
        sw.Start();
        for (int i = 0; i < 1000; i++)
        {
            bi++;
            Console.WriteLine($"{i}th try : {bi} ({sw.Elapsed.ToString("mm\\:ss\\.ff")})");

            bool b = IsPrime(bi);
            if (b)
            {
                Console.WriteLine($"{bi} is a prime number");
            }

            //GC.Collect();
        }
        sw.Stop();

        Console.Read();
    }

    static private bool IsPrime(BigInteger n)
    {
        if (n <= 1)
            return false;
        else if (n <= 3)
            return true;
        else if (n % 2 == 0 || n % 3 == 0)
            return false;
        for (BigInteger i = 5; i * i <= n; i += 6)
        {
            if (n % i == 0 || n % (i + 2) == 0)
                return false;
        }

        return true;

    }

程序是否冻结取决于变量exp。我测试了exp的几个值。

  • exp)的值:(程序冻结的i
  • 10:没有冻结(应用程序在不到一秒钟内完成
  • 15:没有冻结(但控制台窗口每2秒刷新一次)
  • 17:没有冻结(但是控制台窗口每17秒刷新一次)
  • 20:39
  • 25:13
  • 30:37
  • 50:27
  • 100:37

iexp增加时单调上升并不奇怪。所以我运行了exp = 100三次的程序,但得到了相同的结果。这些数字似乎是可重复和可靠的。

我知道有比这更好地测试素性的算法,但我稍后会尝试。首先,我想检查一下程序的整个行为。

我用google搜索&#34; biginteger console freeze c#&#34;对于这个问题,发现了两篇文章。

  1. MillerRabin primality test in C#
  2. C# BigInteger and int How to save memory?
  3. 第一个说&#34;冻结&#34;和&#34; Biginteger&#34;但答案并没有多大帮助。第二个提到保存内存所以我认为问题是关于垃圾收集。然后我在GC.Collect()循环(注释掉的行)的末尾添加了for,但这并没有解决问题。我得到了同样的结果。

    我该如何解决这个问题?

    环境

    • Windows 8
    • Visual Studio 2017
    • C#
    • .NET Framework 4.6.1

1 个答案:

答案 0 :(得分:1)

你的算法基本上说:

  你能被2整除吗? 3怎么样? 5点左右? 7? 11? 13? 17? 19?

等等

对于小输入值,检查所有这些排列很快。对于较大的输入值,如果较大的输入值具有较小的因子(例如2,3,5或37),则可以快。

但是如果大输入缺少一个小因素(或者因为它是素数,或者因为它的最小因子非常大),你的算法必须做很多检查。基本上它必须检查三分之一(即每六个中有两个)数字直到输入的平方根(直到找到匹配)。对于大数字,这涉及很多的计算。

如果花费的时间太长,则需要编写更好/更快的IsPrime算法。 This answer在这方面可能会有所帮助。

您还可以考虑存储known 素数的部分列表,以便快速查找这些数字(例如,从数据库)而不是“计算”。

回复:

  

(但控制台窗口仅每17秒刷新一次)

这是因为一些输入确实是素数 - 因此需要17秒左右来验证(即检查每个排列)。对于你来说看起来就像控制台每17秒刷新一次,而是计算 17秒。然后随后的计算非常快(因为它们不是素数) - 所以它看起来像是“批量”出来。