【问题标题】:Faster Way to Convert Large binary String to BigInteger将大型二进制字符串转换为 BigInteger 的更快方法
【发布时间】:2019-05-29 11:22:23
【问题描述】:

下面的代码将大二进制 string binaryAsString = "1010101011101011......." 转换为 BigInteger 十进制,但这非常慢,需要很长时间才能完成。有没有更快的方法来完成这项工作?在此之前,我在将BitArray 转换为string 时遇到了问题。我的第一个代码花了很长时间,但我发现了新代码,它的速度比我想象的要快得多。我希望我能找到一种类似的更快的方法来做到这一点,因为这确实需要很长时间。

我尝试使用String whatever = Convert.ToString(binaryAsString, 2);,但这根本不起作用。

// converting the binary String to decimal 
BigInteger Decimalvalue = 0;  

foreach (char c in binaryAsString) 
{
    Decimalvalue <<= 1;

    Decimalvalue += c == '1' ? 1 : 0;

} 

我想要更快的代码来完成上面代码应该做的事情。

【问题讨论】:

  • 您希望将带有 0 和 1 的字符串转换为等效的十进制数,或者您希望保留 0 和 1 并将字符串转换为数字?字符串可以有多大?
  • 我希望将 0 和 1 转换为等效的十进制数。你的意思是保持 0 和 1 并将字符串转换为 number 。非常大,可能相当于 1 GB 文件,但现在非常慢,相当于 1 MB
  • 二进制值 11 是十进制的 3 也是 11 十一,10 保留
  • 不,我想要的是十进制的 11 = 3

标签: c#


【解决方案1】:

您可以使用 or 运算符而不是 +。

进一步,可以缓存1的大整数值(整数被装箱成大整数)

BigInteger one = 1;
foreach (char c in s)
{
    integer <<= 1;
    if (c == '1')
        integer |= one;
}

在我的测试中它明显更快。

【讨论】:

  • 是的,这有点快,但是对于 700kb 的文件,它需要 29 分钟并且还没有完成,我需要更快的方法
【解决方案2】:

我认为按每个字符处理大字符串不是一个好方法。

char c in binaryAsString

查看BigInteger的构造函数,可以发现:

BigInteger(Byte[])

所以第一件事是将字符串转换为字节数组,然后构造你的大整数。其余代码均来自此答案:Convert a binary string representation to a byte array

int numOfBytes = binaryAsString.Length / 8;
byte[] bytes = new byte[numOfBytes];
for(int i = 0; i < numOfBytes; ++i)
    bytes[i] = Convert.ToByte(binaryAsString.Substring(8 * i, 8), 2);

选项 1。使用string.PadLeft

if((binaryAsString.Length % 8) != 0)
{
    var totalWidth = (binaryAsString.Length / 8 + 1) * 8;
    binaryAsString = binaryAsString.PadLeft(totalWidth, '0');
}

选项 2。从尾部转换

int numOfBytes = binaryAsString.Length / 8;
if((binaryAsString.Length % 8) != 0)
    numOfBytes++;
byte[] bytes = new byte[numOfBytes];
for(int i = 1; i <= numOfBytes; ++i)
{
    int start = binaryAsString.Length - i * 8;
    int length = 8;
    if(start < 0)
    {
        length += start;
        start = 0;
    }
    bytes[numOfBytes - i] = Convert.ToByte(binaryAsString.Substring(start, length), 2);
}

【讨论】:

  • ok 是 Decimalvalue = new BigInteger(bytes); ,兄弟,这太神奇了,这快了 100000 倍,但有一个问题 ans 不正确,我得到十进制值 -10292496836912565244 .....
  • 去除负数 >> 防止 BigInteger(Byte[]) 构造函数将负值的二进制补码表示与正值的符号和幅度表示混淆,正值在通常会设置字节数组中最后一个字节的最高有效位应该包括一个值为 0 的附加字节。所以我添加了这个代码 Decimalvalue = new BigInteger(bytes.Concat(new byte[] { 0 }).ToArray( ));但是当我想将二进制文件恢复为二进制文件时,它是不同的 0 和 1,我使用它来将其转换回二进制文件 > 下面
  • StringBuilder sb = new StringBuilder(); while (Decimalvalue > 0) { sb.Insert(0, Decimalvalue % 2);十进制值/= 2; } /// 字符串 RevercBinary = sb.ToString();
  • 长度是 8 的倍数,因为每个字节有 8 位。您的输入数据可能会从头部修剪“0”,因此您可以使用string.PadLeft 添加一些“0”以使整个字符串的长度为8 倍。另一个想法是将此字符串从尾部转换为字节。
  • 两个选项都给了我相同的 ans ,但我注意到为什么 0 和 1 永远不会返回相同的原因是因为如果我有 00000101 将转换为 5 ,但是当我将它转换回二进制时5 将只有 101,我怎样才能将它恢复到 00000101
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-02
  • 2014-04-29
  • 2012-10-26
  • 2021-02-24
  • 2018-12-12
相关资源
最近更新 更多