最有效的方式来存储和检索512位数字?

时间:2014-04-02 19:43:53

标签: c# bitarray

我有一个512个字符的字符串,只包含0,1。我试图将它表示为一个可以节省空间的数据结构。 BitArray是最有效的方式吗?

我也在考虑使用16 int32来存储数字,然后是16 * 4 = 64字节。

4 个答案:

答案 0 :(得分:1)

效率最高可能意味着许多不同的事情......

  1. 从内存管理的角度来看效率最高吗?
  2. 从CPU计算的角度来看效率最高吗?
  3. 从使用角度来看效率最高? (关于编写使用数字进行计算的代码)
  4. 1 - 使用byte[64]long[8] - 如果您没有进行计算或不介意编写自己的计算。

    对于3肯定BigInteger是要走的路。您已经定义了数学函数,只需要将二进制数转换为十进制数。

    编辑:由于尺寸问题,听起来你不想要BigInteger ......不过我认为你会发现你当然要把它解析为枚举/产量组合你在哪里解析它一次并且不要同时在内存中保存整个数据结构。

    话虽如此......我可以帮你解决你的字符串到Int64的数组中的问题...感谢King King参与这个linq语句的一部分here

    // convert string into an array of int64's
    // Note that MSB is in result[0]
    var result = input.Select((x, i) => i)
                    .Where(i => i % 64 == 0)
                    .Select(i => input.Substring(i, input.Length - i >= 64 ? 
                        64 : input.Length - i))
                    .Select(x => Convert.ToUInt64(x, 2))
                    .ToArray();          
    

    如果您决定要使用不同的数组结构byte[64]或其他任何应该易于修改的结构。

    编辑2:好的我感到无聊所以我写了一个EditDifference函数以获得乐趣...在这里你去......

    static public int GetEditDistance(ulong[] first, ulong[] second)
    {
        int editDifference = 0;
        var smallestArraySize = Math.Min(first.Length, second.Length);
        for (var i = 0; i < smallestArraySize; i++)
        {
            long signedDifference;
            var f = first[i];
            var s = second[i];
            var biggest = Math.Max(f, s);
            var smallest = Math.Min(f, s);
            var difference = biggest - smallest;
            if (difference > long.MaxValue)
            {
                editDifference += 1;
                signedDifference = Convert.ToInt64(difference - long.MaxValue - 1);
            }
            else
                signedDifference = Convert.ToInt64(difference);
            editDifference += Convert.ToString(signedDifference, 2)
                .Count(x => x == '1');
        }
        // if arrays are different sizes every bit is considered to be different
        var differenceOfArraySize = 
            Math.Max(first.Length, second.Length) - smallestArraySize;
        if (differenceOfArraySize > 0)
            editDifference += differenceOfArraySize * 64;
        return editDifference;
    }
    

答案 1 :(得分:0)

效率最高的是八个UInt64 / ulongInt64 / long类型变量(或单个数组),尽管这可能不是查询的最佳选择/设置。实际上,解决这个问题的一种方法是使用BitArray(它基本上是前一种方法的包装器,包括额外的开销[1])。无论是易于使用还是高效存储,这都是一个选择问题。

如果这还不够,您可以随时选择应用压缩,例如RLE编码或各种其他广泛可用的编码方法(gzip / bzip / etc ...)。这需要额外的处理能力。

这取决于您对效率的定义。

[1]附加开销,与存储开销一样。 BitArray在内部使用Int32 - 数组来存储值。除了BitArray存储其当前的变异版本,“已分配”的数量和同步根。尽管对于较小数量的值,开销可以忽略不计,但如果将大量内容保留在内存中,则可能会出现问题。

答案 2 :(得分:0)

使用.NET中的BigInteger。它可以轻松支持512位数字以及对这些数字的操作。

BigInteger.Parse("your huge number");

答案 3 :(得分:0)

BitArray(包含512位),byte[64]int[16]long[8](或List<>个变体)或BigInteger将一切都比你的String更有效率。我一般说byte[]是表示此类数据的最惯用/典型的方式。例如,ComputeHash使用byte[]Streams处理byte[],如果您将此数据存储为数据库中的BLOB,byte[]将是最自然的方式来处理这些数据。出于这个原因,使用它可能是有意义的。

另一方面,如果此数据代表一个数字,你可能会做数字事情喜欢加法和减法,你可能想要使用BigInteger

这些方法的性能大致相同,因此您应该主要根据有意义的事情进行选择,其次要根据您的使用情况进行基准测试。