How does the BigInteger store values internally?

后端 未结 1 1841
甜味超标
甜味超标 2020-12-22 04:09

The BigInteger class has a method that returns a byte array. Is that indicative of the fact that the class uses a byte array internally as well to store numbers?

Thi

1条回答
  •  失恋的感觉
    2020-12-22 04:58

    According to the reference source it appears that it stores it's information as a uint[] for the data and a int for the sign.

    namespace System.Numerics
    {
        /// Represents an arbitrarily large signed integer.
        [Serializable]
        public struct BigInteger : IFormattable, IComparable, IComparable, IEquatable
        {
    
        // For values int.MinValue < n <= int.MaxValue, the value is stored in sign
        // and _bits is null. For all other values, sign is +1 or -1 and the bits are in _bits
        internal int _sign;
        internal uint[] _bits;
    

    Here is the code it executes to perform ToByteArray()

        // Return the value of this BigInteger as a little-endian twos-complement
        // byte array, using the fewest number of bytes possible. If the value is zero,
        // return an array of one byte whose element is 0x00.
        public byte[] ToByteArray() {
            if (_bits == null && _sign == 0)
                return new byte[] { 0 };
    
            // We could probably make this more efficient by eliminating one of the passes.
            // The current code does one pass for uint array -> byte array conversion,
            // and then another pass to remove unneeded bytes at the top of the array.
            uint[] dwords;
            byte highByte;
    
            if (_bits == null) {
                dwords = new uint[] { (uint)_sign };
                highByte = (byte)((_sign < 0) ? 0xff : 0x00);
            }
            else if(_sign == -1) {
                dwords = (uint[])_bits.Clone();
                NumericsHelpers.DangerousMakeTwosComplement(dwords);  // mutates dwords
                highByte = 0xff;
            } else {
                dwords = _bits;
                highByte = 0x00;
            }
    
            byte[] bytes = new byte[checked(4 * dwords.Length)];
            int curByte = 0;
            uint dword;
            for (int i = 0; i < dwords.Length; i++) {
                dword = dwords[i];
                for (int j = 0; j < 4; j++) {
                    bytes[curByte++] = (byte)(dword & 0xff);
                    dword >>= 8;
                }
            }
    
            // find highest significant byte
            int msb;
            for (msb = bytes.Length - 1; msb > 0; msb--) {
                if (bytes[msb] != highByte) break;
            }
            // ensure high bit is 0 if positive, 1 if negative
            bool needExtraByte = (bytes[msb] & 0x80) != (highByte & 0x80);
    
            byte[] trimmedBytes = new byte[msb + 1 + (needExtraByte ? 1 : 0)];
            Array.Copy(bytes, trimmedBytes, msb + 1);
    
            if (needExtraByte) trimmedBytes[trimmedBytes.Length - 1] = highByte;
            return trimmedBytes;
        }
    

    0 讨论(0)
提交回复
热议问题