C# Нужна лучшая логика для преобразования biginteger в двоичные и наоборот

Нужна лучшая логика производительности для преобразования biginteger в двоичные и наоборот.

  • Нужно сократить время
  • binaryResult и binarystringInput должны совпадать после преобразования

Преобразование двоичной строки в Biginteger: занимает [7663] миллисекунды (ожидается, 3000 мс или половина от моего результата)

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

// Результат в декабре

Преобразование BigIntger в BinaryString: занимает [27483] миллисекунд (ожидаемое 10000мс или половина от моего результата)

string binaryResult = "";

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

// Результат в binaryResult

1 ответ

Решение

Вот парсер.

Как сказал @Micke, BigInteger может принять массив байтов в качестве входных данных. Таким образом, вместо того, чтобы постоянно добавлять вместе BigIntegers (и, таким образом, создавать и уничтожать множество байтовых массивов внутри BigInteger), давайте просто соберем наш собственный байтовый массив вручную.

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

Имея это в виду, вот простой парсер:

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;
}
Другие вопросы по тегам