C# 需要更好的逻辑来将 biginteger 转换为二进制,反之亦然
C# Need better logic for biginteger to binary conversions and vice versa
需要更好的性能逻辑来实现双整数到二进制的转换,反之亦然。
- 需要缩短时间
- binaryResult 和 binarystringInput 转换后应该相同
BinaryString 到 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);
}
// 12 月的结果
BigIntger 到 BinaryString 的转换:需要 [27483] 毫秒(预计 10000 毫秒或我的结果的一半)
string binaryResult = "";
while (dec != 0)
{
BigInteger nextDigit = dec & 0x01;
binaryResult = nextDigit + binaryResult;
dec = dec >> 1;
}
// binaryResult 中的结果
这是一个解析器。
正如@Micke所说,BigInteger
可以将字节数组作为输入。因此,与其不断地将 BigInteger 相加(从而创建和销毁 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;
}
需要更好的性能逻辑来实现双整数到二进制的转换,反之亦然。
- 需要缩短时间
- binaryResult 和 binarystringInput 转换后应该相同
BinaryString 到 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);
}
// 12 月的结果
BigIntger 到 BinaryString 的转换:需要 [27483] 毫秒(预计 10000 毫秒或我的结果的一半)
string binaryResult = "";
while (dec != 0)
{
BigInteger nextDigit = dec & 0x01;
binaryResult = nextDigit + binaryResult;
dec = dec >> 1;
}
// binaryResult 中的结果
这是一个解析器。
正如@Micke所说,BigInteger
可以将字节数组作为输入。因此,与其不断地将 BigInteger 相加(从而创建和销毁 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;
}