简体   繁体   中英

C# Need better logic for biginteger to binary conversions and vice versa

Need better performance logic for biginteger to binary conversions and vice versa.

  • Need to reduce time
  • binaryResult and binarystringInput should same after conversions

BinaryString to Biginteger conversion: Takes [7663] milli seconds (Expected 3000ms or half from my result )

    var binarystringInput = "100011101001----etc"; // Length = 250000 
            // Find binarystringInput here "http://notepad.cc/share/RzOfxBWsiJ"

            BigInteger dec = new BigInteger(0);               

            for (int ii = 0; ii < binarystringInput.Length; ii++)
            {
                if (binarystringInput[binarystringInput.Length - ii - 1] == '0') continue;
                dec += BigInteger.Pow((new BigInteger(2)), ii);
            }

// Result in dec

BigIntger to BinaryString Conversion : Takes [27483] milli seconds (Expected 10000ms or half from my result )

string binaryResult = "";

            while (dec != 0)
            {
                BigInteger nextDigit = dec & 0x01;
                binaryResult = nextDigit + binaryResult;
                dec = dec >> 1;
            }

// Result in binaryResult

Here's a parser.

Just as @Micke said, BigInteger can take a byte array in as its input. So instead of constantly adding together BigIntegers (and thus creating and destroying many byte arrays internal to BigInteger), lets just put together our own byte array by hand.

One detail to keep in mind is that BigInteger accepts twos-complement values. If the highest bit is set in the highest-order byte, then it thinks the value is negative. If you always prepend an empty byte first, then you can disable that behavior and treat bitstrings as unsigned, which is an assumption my code makes.

With that in mind, here is a simple parser:

public static BigInteger ParseBinary( string bitstring )
{
    byte[] raw;

    int rawLength;
    int rawPosition;
    int bitStart = 0;


    // Calculate the total number of bytes we'll need to store the 
    // result. Remember that 10 bits / 8 = 1.25 bytes --> 2 bytes. 
    rawLength = (int)Math.Ceiling( bitstring.Length / 8.0 );

    // Force BigInteger to interpret our array as an unsigned value. Leave
    // an unused byte at the end of our array.
    raw = new byte[rawLength + 1];

    rawPosition = rawLength - 1;

    // Lets assume we have the string 10 1111 0101
    // Lets parse that odd chunk '10' first, and then we can parse the rest on nice
    // and simple 8-bit bounderies. Keep in mind that the '10' chunk occurs at indicies 
    // 0 and 1, but represent our highest order bits.

    if ( rawLength * 8 != bitstring.Length )
    {
        int leftoverBits = bitstring.Length % 8;

        raw[rawPosition] = ParseChunk( bitstring, 0, leftoverBits );
        rawPosition--;
        bitStart += leftoverBits;
    }

    // Parse all of the 8-bit chunks that we can.
    for ( int i = bitStart; i < bitstring.Length; i += 8 )
    {
        raw[rawPosition] = ParseChunk( bitstring, i, 8 );
        rawPosition--;
    }

    return new BigInteger( raw );
}

private static byte ParseChunk( string bitstring, int startPosition, int run )
{
    byte result = 0;
    byte temp;

    for ( int i = 0; i < run; i++ )
    {
        // Abuse the unicode ordering of characters.
        temp = (byte)(bitstring[startPosition + i] - '0');
        result |= (byte)(temp << run - i - 1);
    }

    return result;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM