【问题标题】:Calculating the Power set of large string array in C# [duplicate]在C#中计算大字符串数组的幂集[重复]
【发布时间】:2016-03-31 12:17:02
【问题描述】:

我想计算字符串数组的幂集(将其视为一个集合)。当我超过 26 个元素时,它会抛出内存不足异常。

List<int> ff = new List<int>();
double length = Math.Pow(2, 29);
for (int i = 0; i < length; i++)
{
   ff.Add(1);
}

如果您运行上面的代码,它将产生该异常。集合的大小可能会达到 1000。因此该集合的幂集大小将是 2^1000。

我该如何处理?

编辑

我知道上面的代码不是幂集的函数。我只是在检查 c# 能够容纳多大的数组。

 private static Dictionary<int, object> PowerSetB(string[] input)
        {
            int n = input.Length;
            // Power set contains 2^N subsets.
            int powerSetCount = 1 << n;
            var ans = new Dictionary<int, object>();

            for (int setMask = 0; setMask < powerSetCount; setMask++)
            {
                var s = new ArrayList();
                for (int i = 0; i < n; i++)
                {
                    // Checking whether i'th element of input collection should go to the current subset.
                    if ((setMask & (1 << i)) > 0)
                        s.Add(input[i]);
                }
                ans[setMask] = s;
            }
            return ans;
        }

以上代码是我的幂集函数。

提前谢谢你。

【问题讨论】:

  • 你需要一个能够容纳这么大数字的类型。
  • 会是这样吗?
  • 您不能在 64 位(即 2^64)地址空间中容纳 2^1000 个整数。您不能购买 2^64,即16 exbibytes 的内存。 1 GB 是 2^30。将数据存储到文件中。但是,您可以创建一个大缓冲区并在它填满时将其写出,而不是存储每个数字
  • 什么是实际问题,即你想用ff列表做什么?

标签: c# out-of-memory


【解决方案1】:

您真的要将所有项目存储在内存中吗?我建议使用 IEnumerable&lt;int&gt; 而不是 materialized List&lt;int&gt;:

// just enumeration, coefficients aren't stored
public static IEnumerable<int> Serie(Func<int, int> coefByIndex) {
  if (null == coefByIndex)
    throw new ArgumentNullException("coefByIndex");

  for (int i = 0; ; ++i)
    yield return coefByIndex(i);
}

// Let's sum up all 2**29 values, 
// i.e. compute f(1) summing up 2**29 items (it's a long process...)
// sum = 1.44115187606094E+17 (diverges, as we might have expected)
Double sum = Serie(index => index)
  .Select(x => x * 1.0)
  .Take(1 << 29)
  .Sum();

编辑:不要实现 (Dictionary&lt;int, object&gt;) 巨大的结果!提供IReadOnlyDictionary&lt;int, int[]&gt; 接口,但不提供Dictionary&lt;int, object&gt; 的实现,
像这样的:

  // ArrayList is an obsolete collection;
  // int[] far more natural here
  public sealed class PowerSet: IReadOnlyDictionary<int, int[]> {
    private int m_Power;

    private int[] getItem(int index) {
      int[] result = new int[m_Power];

      for (int i = 0; i < m_Power; ++i) {
        result[i] = index % 2;

        index /= 2;
      }

      return result;
    }

    public PowerSet(int power) {
      m_Power = power;
    }

    public int[] this[int key] {
      get {
        if (key >= 0 && key < Count)
          return getItem(key);
        else
          throw new ArgumentOutOfRangeException("key");
      }
    }

    public int Count {
      get {
        return 1 << m_Power;
      }
    }

    public IEnumerable<int> Keys {
      get {
        return Enumerable.Range(0, Count);
      }
    }

    public IEnumerable<int[]> Values {
      get {
        return Enumerable.Range(0, Count).Select(index => getItem(index));
      }
    }

    public bool ContainsKey(int key) {
      return key >= 0 && key < Count;
    }

    public IEnumerator<KeyValuePair<int, int[]>> GetEnumerator() {
      return Enumerable
        .Range(0, Count)
        .Select(index => new KeyValuePair<int, int[]>(index, getItem(index)))
        .GetEnumerator();
    }

    public bool TryGetValue(int key, out int[] value) {
      if (key >= 0 && key < Count) {
        value = getItem(key);

        return true;
      }

      value = null;
      return false;
    }

    IEnumerator IEnumerable.GetEnumerator() {
      return this.GetEnumerator();
    }
  }

  ... 

  // Just an easy call
  private static IDictionary<int, int[]> PowerSetB(string[] input) {
    return new PowerSet(input.Length);
  }

【讨论】:

  • 我必须存储所有这些项目,因为我得到的电源组需要进一步附加才能获得主要结果。
  • @Artiga:为了追加IEnumerable&lt;int&gt;,你可以试试.ConcatSerie(index =&gt; index).Take(10).Concat(Serie(index =&gt; index * index))
  • 如何使用 IEnumnertable 修改我的“PowerSetB”函数(我已在 EDIT 中编写)?
  • @Artiga 你想做什么?您可以拥有 RAM 可以处理的最大数组,但您甚至找不到足够大的 磁盘数组 来存储那么多 4 字节整数。无论您的实际问题是什么,中间存储都是错误的方法
  • @PanagiotisKanavos 那么正确的方法是什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-29
  • 2020-04-19
  • 2012-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多