我在做一些项目欧拉练习,我碰到一个场景,我已经想这比2,147,483,647(上限更大的阵列int
在C#).
当然这些是大型阵列,但是,例如,我不能这样做
// fails bool[] BigArray = new BigArray[2147483648]; // also fails, cannot convert uint to int ArrayList BigArrayList = new ArrayList(2147483648);
那么,我可以拥有更大的阵列吗?
编辑:你知道,这是阿特金的筛子,所以我只想要一个非常大的:D
无论何时你正在使用这么大的数组,你应该尝试找到一个更好的解决问题的方法.但话虽如此,我仍会尝试回答你的问题.
如本文所述,.Net中的任何对象都有2 GB的限制.适用于所有x86,x64和IA64.
与32位Windows操作系统一样,在64位Windows操作系统上运行64位托管应用程序时,可以创建的对象大小限制为2GB.
此外,如果在堆栈上定义一个太大的数组,则会出现堆栈溢出.如果在堆上定义数组,它将尝试在一个大的连续块中分配它.最好使用在堆上具有隐式动态分配的ArrayList.这不会让你超过2GB,但可能会让你更接近它.
我认为只有在使用x64或IA64架构和操作系统时,堆栈大小限制才会更大.使用x64或IA64,您将拥有64位可分配内存而不是32位.
如果您无法一次性分配数组列表,则可以将其分配.
使用数组列表并在具有6GB RAM的x64 Windows 2008计算机上一次添加1个对象,我可以获得最多的ArrayList是大小:134217728.所以我真的认为你必须找到一个更好的解决方案来解决你的问题没有使用那么多的内存.也许写入文件而不是使用RAM.
即使在64位上,数组限制也是固定为int32.单个对象的最大大小上限.但是,你可以很容易地得到一个漂亮的大锯齿状阵列.
更差; 因为x64中的引用较大,对于ref-type数组,实际上在单个数组中获得的元素较少.
看到这里:
我收到了一些关于为什么64位版本的2.0 .Net运行时仍然有阵列最大大小限制为2GB的问题.鉴于它似乎是最近的一个热门话题,我想了一点背景,并讨论了解决这个限制的选项是有序的.
首先是一些背景; 在2.0版本的.Net运行时(CLR)中,我们做出了有意识的设计决策,将GC Heap中允许的最大对象大小保持在2GB,即使在64位版本的运行时也是如此.这与32位CLR的当前1.1实现相同,但是你很难真正设法在32位CLR上分配2GB对象,因为虚拟地址空间太碎片而不能真实地找到2GB洞.通常人们并不特别关心在实例化(或任何接近)时创建> 2GB的类型,但是由于数组只是在托管堆中创建的一种特殊类型的托管类型,因此它们也受到此限制.
应该注意的是,在.NET 4.5中,gcAllowVeryLargeObjects标志可以选择性地删除内存大小限制,但是,这不会更改最大维度大小.关键是如果你有自定义类型的数组或多维数组,那么你现在可以超过2GB的内存大小.
你根本不需要一个大的数组.
当您的方法遇到资源问题时,不要只看如何扩展资源,也请查看方法.:)
这是一个使用3 MB缓冲区来使用Eratosthenes筛子计算质数的类.该类记录您计算素数的距离,当需要扩展范围时,它会创建一个缓冲区来测试另外300万个数字.
它将找到的素数保留在列表中,当扩展范围时,使用previos素数来排除缓冲区中的数字.
我做了一些测试,大约3 MB的缓冲区是最有效的.
public class Primes { private const int _blockSize = 3000000; private List_primes; private long _next; public Primes() { _primes = new List () { 2, 3, 5, 7, 11, 13, 17, 19 }; _next = 23; } private void Expand() { bool[] sieve = new bool[_blockSize]; foreach (long prime in _primes) { for (long i = ((_next + prime - 1L) / prime) * prime - _next; i < _blockSize; i += prime) { sieve[i] = true; } } for (int i = 0; i < _blockSize; i++) { if (!sieve[i]) { _primes.Add(_next); for (long j = i + _next; j < _blockSize; j += _next) { sieve[j] = true; } } _next++; } } public long this[int index] { get { if (index < 0) throw new IndexOutOfRangeException(); while (index >= _primes.Count) { Expand(); } return _primes[index]; } } public bool IsPrime(long number) { while (_primes[_primes.Count - 1] < number) { Expand(); } return _primes.BinarySearch(number) >= 0; } }