Каков предел типа значения BigInteger в C#?

как описано в MSDN BigInteger - это :

неизменяемый тип, представляющий произвольно большое целое число, теоретически ценность не имеет ни верхних, ни нижних границ.

как я вижу, BigInteger является ValueType, насколько я знаю, ValueType должен иметь максимальный размер 16 байт.

MSDN идет дальше, говоря:

исключение OutOfMemoryException может быть вызвано для любой операции, которая вызывает Значение BigInteger слишком велико.

и еще :

хотя этот процесс прозрачен для вызывающего абонента, он вызывает производительности. В некоторых случаях, особенно при повторении операции выполняются в цикле на очень больших значений BigInteger

как он может хранить такие большие значения, как double.MaxValue + double.MaxValue ? Мне сказали, что он имеет ReferenceType obejects внутри него, но все, что я могу найти здесь в его определении в VisualStudio-это ValueTypes.

каков его реальный предел ? И даже если его нет, как он" как тип значения " может хранить весь этот объем данных ?

2 ответов


как я вижу, BigInteger-это ValueType, насколько я знаю, ValueType должен иметь максимальный размер 16 байтов.

нет, это неправда. Это обычных limit, но для типа значения вполне возможно взять больше, чем это. Например:

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...
}

(мусульманский ответ Бен Дау показывает одну текущую реализацию с помощью int и uint[], но, конечно,подробности из этого намеренно скрыты.)

так стоимостью of a BigInteger все еще может быть маленьким, но он может ссылаться на большой кусок памяти - и если недостаточно памяти для выделения того, что требуется при выполнении какой-либо операции, вы получите исключение.

как он может хранить такие большие значения, как double.MaxValue + двойной.Максвеллову ?

хорошо BigInteger на чисел, поэтому я бы не хотел использовать его для чего-либо, связанного с double... но принципиально ограничения будут вокруг сколько памяти у вас и размер массива CLR может справиться. На самом деле, вы бы говорили о огромный числа до фактического достижения предела для любого конкретного числа-но если у вас есть газиллионы меньших чисел, это, очевидно, имеет большую память требования тоже.


в качестве подтверждения ответа от Джона Скита я посмотрел на исходный код BigInteger. На самом деле он содержит два внутренних свойства:

internal int _sign;
internal uint[] _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: Я должен был прокомментировать J. S. ответ, но комментарий слишком короткий. Чтобы просмотреть исходный код, либо скачать декомпилировать System.Numerics.dll.