C# 在内存中保存大量整数列表,以便快速访问
首先,有一点背景:我喜欢处理projecteuler问题(),但其中许多问题需要大量的计算,所以我尝试将已知常量保存在内存中,这样就不必每次都重新计算它们。包括n!,nPr、nCr和素数列表。对于这个问题,让我们只使用素数,因为任何使用素数的解都可以很容易地移植到其他解 问题是:假设我想在内存中保存前1000000个素数,以便在执行大量计算时重复访问。第1000000个素数是15485863,所以整数在这里就可以了。我需要以这样的方式保存这些值,即access为O(1),因为这些值将被大量访问 到目前为止,我所尝试的: 很明显,我不能把所有1000000都放在一个cs文件中,因为VisualStudio引发了一个问题。我一直在尝试使用一个分部类和2-DC# 在内存中保存大量整数列表,以便快速访问,c#,C#,首先,有一点背景:我喜欢处理projecteuler问题(),但其中许多问题需要大量的计算,所以我尝试将已知常量保存在内存中,这样就不必每次都重新计算它们。包括n!,nPr、nCr和素数列表。对于这个问题,让我们只使用素数,因为任何使用素数的解都可以很容易地移植到其他解 问题是:假设我想在内存中保存前1000000个素数,以便在执行大量计算时重复访问。第1000000个素数是15485863,所以整数在这里就可以了。我需要以这样的方式保存这些值,即access为O(1),因为这些值将被大量访问
List
这种方法确实有效,因为它很容易通过列表枚举,IsPrime(n)
检查也相当简单(二进制搜索)。这种方法的最大缺点是VS开始崩溃,因为每个文件中都有大约75000个整数(根据间距大约8000行)。事实上,我对这些文件的大部分编辑都必须在NPP中完成,以防止VS挂起/崩溃
我考虑过的其他事情:
我最初从一个文本文件中读取数字,可以在程序中执行,但很明显,我希望在启动时执行此操作,然后只需获得可用的值。我也考虑过将它们转储到sql中,但最终它们需要存储在内存中。对于内存中的存储,我考虑了memcache,但我对它了解得不够,不知道它在查找中的效率有多高
最后,这归结为两个问题:
快速提示:是的,我知道如果我只做了15页,那么我就不会有全部1000000页,因为15485863页在第16页。很好,就我们这里的目的而言,这已经足够了。在启动时从单个文本文件中引入它们。这些数据不应该在源文件中(正如您所发现的) 将它们存储在
HashSet
中,因此对于任何数字n
,isPrime=n=>primeHashSet.Contains(n)
。这将为您提供所需的O(1)复杂性
HashSet<int> primeHashSet = new HashSet<int>(
File.ReadLines(filePath)
.AsParallel() //maybe?
.SelectMany(line => Regex.Matches(line, @"\d+").Cast<Match>())
.Select(m => m.Value)
.Select(int.Parse));
Predicate<int> isPrime = primeHashSet.Contains;
bool someNumIsPrime = isPrime(5000); //for example
HashSet primeHashSet=新HashSet(
File.ReadLines(文件路径)
.AsParallel()//可能吧?
.SelectMany(line=>Regex.Matches(line,@“\d+”).Cast())
.选择(m=>m.Value)
.选择(int.Parse));
谓词isPrime=primeHashSet.Contains;
bool-someNumIsPrime=isPrime(5000)//例如
在我的机器上(承认相当快),加载大约需要300毫秒。在启动时从单个文本文件中加载。这些数据不应该在源文件中(正如您所发现的) 将它们存储在
HashSet
中,因此对于任何数字n
,isPrime=n=>primeHashSet.Contains(n)
。这将为您提供所需的O(1)复杂性
HashSet<int> primeHashSet = new HashSet<int>(
File.ReadLines(filePath)
.AsParallel() //maybe?
.SelectMany(line => Regex.Matches(line, @"\d+").Cast<Match>())
.Select(m => m.Value)
.Select(int.Parse));
Predicate<int> isPrime = primeHashSet.Contains;
bool someNumIsPrime = isPrime(5000); //for example
HashSet primeHashSet=新HashSet(
File.ReadLines(文件路径)
.AsParallel()//可能吧?
.SelectMany(line=>Regex.Matches(line,@“\d+”).Cast())
.选择(m=>m.Value)
.选择(int.Parse));
谓词isPrime=primeHashSet.Contains;
bool-someNumIsPrime=isPrime(5000)//例如
在我的(无可否认相当快)机器上,加载大约需要300毫秒。尽管这两种方法都可以工作。在这种特定情况下,使用
谓词
而不是Func
更合适。@AominèI倾向于避免大多数已定义的委托,而支持Func
和操作
,因为在阅读和理解代码时存在间接层Func
和Action
以非常可读的方式宣传其意图(除非参数列表很长)。我不确定使用谓词的方法是什么,但我会在这里尝试一下:)请注意,从包含这么多项的IEnumerable初始化哈希集可能会非常昂贵。你可以先做.ToArray()
做得更好。@spender Right,我想这是一个优先考虑的问题。。)@我刚量过。。。小于3%的速度增益。我觉得自己被骗了:)尽管这两种方法都有效。在这种特定情况下,使用谓词
而不是Func
更合适。@AominèI倾向于避免大多数已定义的委托,而支持Func
和操作
,因为在阅读和理解代码时存在间接层Func
和Action
以非常可读的方式宣传其意图(除非参数列表很长)。我不确定使用谓词的方法是什么,但我会在这里尝试一下:)请注意,从包含这么多项的IEnumerable初始化哈希集可能会非常昂贵。你可以先做.ToArray()
做得更好。@spender Right,我想这是一个优先考虑的问题。。)@我刚量过。。。小于3%的速度增益。我觉得被骗了:)将此作为一个列表是个坏主意,因为您现在将数据存储两次:一次在程序代码中,一次在加载数据时存储在内存中为什么你需要内存中的所有数据?井列表不是O(1)。你可以有O(1)在文件中使用更少的空间并将其存储在文件中我投票将这个问题作为离题题来结束,因为它太宽泛了,但也因为它本质上是一种编程练习,以吸引所有喜欢展示自己聪明的人,而在这个过程中忽略了这一点,因为当前的Upvots清楚地表明了这是一个类似这样的列表这是个坏主意,因为你现在是sto
HashSet<int> primeHashSet = new HashSet<int>(
File.ReadLines(filePath)
.AsParallel() //maybe?
.SelectMany(line => Regex.Matches(line, @"\d+").Cast<Match>())
.Select(m => m.Value)
.Select(int.Parse));
Predicate<int> isPrime = primeHashSet.Contains;
bool someNumIsPrime = isPrime(5000); //for example