Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
907 views
in Technique[技术] by (71.8m points)

c# - How does the BigInteger store values internally?

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?

This is important to know in order to pick the right data types to manipulate binary data. If the class were, for example, to use an Int64 array, then a similar array would be more efficient to manipulate raw data by any calling functions.

As an example, I am calling the ToByteArray method to traverse bytes looking for specific binary patterns.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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
{
    /// <summary>Represents an arbitrarily large signed integer.</summary>
    [Serializable]
    public struct BigInteger : IFormattable, IComparable, IComparable<BigInteger>, IEquatable<BigInteger>
    {

    // 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;
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...