【发布时间】:2017-11-25 11:40:28
【问题描述】:
问题
具有 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) - 10 : 没有冻结(应用在不到一秒的时间内完成
- 15:没有冻结(但是控制台窗口仅每 2 秒刷新一次)
- 17 : 没有冻结(但控制台窗口仅每 17 秒刷新一次)
- 20 : 39
- 25 : 13
- 30 : 37
- 50 : 27
- 100 : 37
很奇怪i 不会随着exp 的增加而单调上升。所以我为exp = 100 运行了三次程序,但得到了相同的结果。这些数字似乎是可重复的和可靠的。
我知道有一些算法可以比这个更好地测试素数,但我稍后会尝试。首先,我想检查程序的整个行为。
我为此问题搜索了“biginteger console freeze c#”,找到了两篇文章。
第一个说“冻结”和“Biginteger”,但答案没有多大帮助。第二个提到节省内存,所以我认为问题与垃圾收集有关。然后我在for 循环(注释掉的行)的末尾添加了GC.Collect(),但这并没有解决问题。我得到了同样的结果。
我应该如何解决这个问题?
环境
- Windows 8
- Visual Studio 2017
- C#
- .NET Framework 4.6.1
【问题讨论】:
-
mjwills,程序在
IsPrime()的 for 循环内循环。这是通过放置一个断点来检查的。 -
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036的最小因子显然是2。所以IsPrime()应该在else if (n % 2 == 0 || n % 3 == 0)上返回false并且应该打印一行。我不确定0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037。我运行程序大约 20 分钟,控制台没有显示任何新行。此外,程序正常运行直到I=35 并突然停在i=36 才有意义。bi的变化很小。 -
哦,我明白了!所以你说的是第 n 行在 17 秒内弹出,第 n+1 行在 17.001 秒内弹出,第 n+2 行在 17.002 秒内弹出,第 n+3 行在 17.003 秒内弹出(列表还在继续)所以它看起来像所有的线条都在 17 秒内准确出现,这是不正确的。非常感谢!
-
众所周知,保理是一个很难快速解决的问题;这就是为什么它是密码系统的基础。您可以做得比现在好得多,但总体上不会非常更好。
标签: c# visual-studio console-application primes freeze