C#中值类型BigInteger的限制是多少?
如MSDN中所描述的BigInteger是:
表示任意大整数的不可变类型,其理论上的值没有上限或下限。
我可以看到BigInteger是一个ValueType
,据我所知,ValueType的最大大小必须为16个字节 。
MSDN进一步说:
对于导致BigInteger值过大的任何操作,都可以抛出OutOfMemoryException。
和更多 :
尽管此过程对调用者是透明的,但它确实会导致性能下降。 在某些情况下,尤其是在非常大的BigInteger值的循环中执行重复操作时
它怎么能存储像double.MaxValue + double.MaxValue
这样的大值double.MaxValue + double.MaxValue
? 我被告知它里面有ReferenceType
obejects,但我在VisualStudio中定义的所有内容都是ValueTypes。
它的真正限制是什么? 即使没有,它如何“作为一种价值类型”设法存储所有数据量?
我可以看到BigInteger是一个ValueType,据我所知,ValueType的最大大小必须为16个字节。
不,那不是真的。 这是一个传统的限制,但是对于值类型而言,完全可行。 例如:
public struct Foo { private readonly int a, b, c, d, e; // Look ma, 20 bytes! }
但是,我强烈怀疑BigInteger
实际上包含对字节数组的引用:
public struct BigInteger { private readonly byte[] data; // Some other fields... }
( Moslem Ben Dhaou的回答显示了使用int
和uint[]
一个当前实现,但当然有意隐藏了这个细节 。)
所以BigInteger
的值仍然可以很小,但它可以引用一大块内存 – 如果没有足够的内存来分配执行某些操作时所需的内存,你将得到一个例外。
它怎么能存储像double这样的大值.MaxValue + double.MaxValue?
BigInteger
用于整数 ,所以我不会特别想用它来做任何与double
事情……但从根本上说,限制将取决于你有多少内存以及CLR可以应对的数组大小用。 实际上,在实际达到任何特定数字的限制之前,你会谈论大量的数字 – 但如果你有数量较少的数字,那显然也有很大的内存需求。
作为Jon Skeet答案的确认,我查看了BigInteger
的源代码。 它实际上包含两个内部属性如下:
internal int _sign; internal uint[] _bits;
_bits
所有私有/公共方法都使用_bits
来读取/写入实际数据。
_sign
用于保持BigInteger
的符号。
私有方法广泛使用二元运算符和计算。 以下是类中使用的一小部分常量,可能反映了一些限制:
private const int knMaskHighBit = -2147483648; private const uint kuMaskHighBit = 2147483648U; private const int kcbitUint = 32; private const int kcbitUlong = 64; private const int DecimalScaleFactorMask = 16711680; private const int DecimalSignMask = -2147483648;
PS:我应该对JS回答发表评论,但是评论太短了。 要查看源代码,请下载或反编译System.Numerics.dll
。