数组的大小是否受int的上限(2147483647)约束?

我正在做一些Project Euler练习,我遇到了一个场景,我想要的数组大于2,147,483,647(C#中int的上限)。

当然这些是大型arrays,但是,例如,我不能这样做

 // fails bool[] BigArray = new BigArray[2147483648]; // also fails, cannot convert uint to int ArrayList BigArrayList = new ArrayList(2147483648); 

那么,我可以拥有更大的arrays吗?

编辑:这是阿特金的筛子 ,你知道,所以我只想要一个非常大的: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。 单个对象的最大大小上限。 但是,你可以很容易地得到一个漂亮的大锯齿状arrays。

更差; 因为x64中的引用较大,对于ref-type数组,实际上在单个数组中获得的元素较少

看到这里 :

我收到了一些关于为什么64位版本的2.0 .Net运行时仍然有arrays最大大小限制为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; } } 

我相信即使在64位CLR中,每个对象也有2GB的限制(或者可能是1GB – 我记不清楚)。 这会阻止您创建更大的数组。 Array.CreateInstance只接受大小的Int32参数的事实也是暗示性的。

更广泛地说,我怀疑如果你需要大的数组,你应该真正改变你接近问题的方式。

我是C#的新手(即本周学习它),所以我不确定ArrayList是如何实现的确切细节。 但是,我猜你没有为ArrayList示例定义类型,那么数组将被分配为对象引用数组。 这可能意味着您实际上正在分配4-8Gb内存,具体取决于体系结构。

根据MSDN ,字节数组的索引不能大于2147483591.对于4.5之前的.NET,它也是数组的内存限制。 在.NET 4.5中,此最大值相同,但对于其他类型,最大值可达2146435071。

这是用于说明的代码:

  static void Main(string[] args) { // ----------------------------------------------- // Pre .NET 4.5 or gcAllowVeryLargeObjects unset const int twoGig = 2147483591; // magic number from .NET var type = typeof(int); // type to use var size = Marshal.SizeOf(type); // type size var num = twoGig / size; // max element count var arr20 = Array.CreateInstance(type, num); var arr21 = new byte[num]; // ----------------------------------------------- // .NET 4.5 with x64 and gcAllowVeryLargeObjects set var arr451 = new byte[2147483591]; var arr452 = Array.CreateInstance(typeof(int), 2146435071); var arr453 = new byte[2146435071]; // another magic number return; }