具有Biginteger计算的控制台应用程序冻结
我正在用C#开发一个控制台应用程序,它测试非常大的数字(10到几十到几百的幂)是否为素数。由于默认整数类型只能处理最多10 ^ 19(long
,ulong
)的数字,因此我使用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
) i
在exp
增加时单调上升并不奇怪。所以我运行了exp
= 100三次的程序,但得到了相同的结果。这些数字似乎是可重复和可靠的。
我知道有比这更好地测试素性的算法,但我稍后会尝试。首先,我想检查一下程序的整个行为。
我用google搜索&#34; biginteger console freeze c#&#34;对于这个问题,发现了两篇文章。
第一个说&#34;冻结&#34;和&#34; Biginteger&#34;但答案并没有多大帮助。第二个提到保存内存所以我认为问题是关于垃圾收集。然后我在GC.Collect()
循环(注释掉的行)的末尾添加了for
,但这并没有解决问题。我得到了同样的结果。
我该如何解决这个问题?
答案 0 :(得分:1)
你的算法基本上说:
你能被2整除吗? 3怎么样? 5点左右? 7? 11? 13? 17? 19?
等等
对于小输入值,检查所有这些排列很快。对于较大的输入值,如果较大的输入值具有较小的因子(例如2,3,5或37),则可以快。
但是如果大输入缺少一个小因素(或者因为它是素数,或者因为它的最小因子非常大),你的算法必须做很多检查。基本上它必须检查三分之一(即每六个中有两个)数字直到输入的平方根(直到找到匹配)。对于大数字,这涉及很多的计算。
如果花费的时间太长,则需要编写更好/更快的IsPrime
算法。 This answer在这方面可能会有所帮助。
您还可以考虑存储known 大素数的部分列表,以便快速查找这些数字(例如,从数据库)而不是“计算”。
回复:
(但控制台窗口仅每17秒刷新一次)
这是因为一些输入确实是素数 - 因此需要17秒左右来验证(即检查每个排列)。对于你来说看起来就像控制台每17秒刷新一次,而是计算 17秒。然后随后的计算非常快(因为它们不是素数) - 所以它看起来像是“批量”出来。