【问题标题】:Interweaving vector of binary representations in C++C++中二进制表示的交织向量
【发布时间】:2011-07-30 13:21:27
【问题描述】:

我在 C++ 中有一个名为 weave 的模板化函数,它接受两个无符号字符并交织它们的二进制扩展并返回一个无符号短整数。它还可以采用两个无符号短裤并交织它们的二进制扩展以返回一个无符号长。这是我写的:

template<class Typeout, class Typein>
Typeout weave(Typein lhs,Typein rhs)
{
//Need to check that Typeout contains enough storage to contain 2*Typein:
assert(sizeof(Typeout)>=2*sizeof(Typein));

Typeout weaved = 0;
for(int k=0;k<sizeof(Typein)*8;k++)
{
    //weave in the kth element of rhs and lhs.
    weaved |=(Typeout(rhs & (Typein)(1<<k)) << k)| (Typeout(lhs & (Typein)(1<<k)) << (k+1));
}
return weaved;
};

现在我无法将向量编织在一起。我想编写一个名为 weave 的函数,它给定一个字符向量,交织它们的所有二进制扩展并返回它。例如,给定一个长度为 4 的无符号字符向量,它应该交织它们的二进制扩展并返回它的表示。我希望这适用于长度大于 8 的字符向量,因此我不能再将它们保存为无符号长长。我想我需要返回一个向量??但我不确定如何减少生成的二进制扩展。

我是 C++ 新手,因此请随时更正代码或给我建议。

提前致谢。

【问题讨论】:

  • 我认为你应该将问题分成两个不同的部分:一个class,它表示对任意内存区域的按位访问,你的算法使用该类的接口。由于前者应该类似于std::vector&lt;bool&gt;,因此您可以简单地编写代码来填充vector&lt;bool&gt;,给定void* 和位数或字节数。这将涉及到向量的堆分配内存的潜在不必要的副本 - 如果需要,可以使用类内部的数据重新实现。如果此评论太含糊而无济于事,请告诉我。
  • 我不确定你的意思。我是否需要一个类来表示按位访问,因为我已经可以直接使用 char、short、long 类型进行按位运算?你的意思是一个类将一个 char 变成一个长度为 8 的 vector 并使用它?问题是我需要非常有效地进行这种编织。
  • @alext87:是的,您已经可以对 char、short、long 进行按位运算,但是解决方案是否不需要将其扩展到更大的块(即 20 字节、300 字节)?我要说的是,您可以单独解决较大块上的按位运算问题,然后使用现有算法,或者您可以通过嵌入处理较大内存块的所有复杂性来使您的算法更加复杂:那就是更难获得和保持正确,但可能提供额外的优化机会。
  • 如果您需要非常高的效率,我建议您放弃常量位移位并预先计算一个表,这样您就可以简单地将一个 8 位字符的位值用作 16 位预位拆分值,然后合并这些。例如,假设输入中的位是 abcdefgh 和 ijklmnop,您将索引到一个表,该表将 abcdefgh 映射到 0a0b0c0d0e0f0g0h 并将 ijklmnop 映射到 0i0j0k0l0m0n0o0p,然后位移一位和 OR。对输入数据中的每个字节执行此操作,然后在最后处理任何奇数小于 8 位的输入段。
  • (如果您想要一个有趣的提示:如果您将其表述为一个虚构的面试问题,那么您现在已经有了 10 个答案,其中一些带有工作代码 - 很有趣地方;-))。

标签: c++ templates binary


【解决方案1】:

编辑:我想我把你的问题弄错了(坦率地说,我仍然不能确切地说 哪里 是你帖子中的实际问题)。如果问题是“我应该把什么作为参数,我应该返回什么类型?”,也许你应该有一个 const T*const std::vector&lt;T&gt;&amp; 参数用于输入,另一个用于输出而不是返回,这将避免分配内存所有权问题。

// base case, weave two 8 bit into a 16 bit word.
uint16_t weave(uint8_t a, uint8_t b) {
    uint16_t x = a, y = b;
    x = (x | (x << 4)) & 0x0F0F;
    x = (x | (x << 2)) & 0x3333;
    x = (x | (x << 1)) & 0x5555;

    y = (y | (y << 4)) & 0x0F0F;
    y = (y | (y << 2)) & 0x3333;
    y = (y | (y << 1)) & 0x5555;

    return x | (y << 1);
}

// most useful way in my opinion
// weave bits from two arrays 'a' and 'b' of size n
// into a pre-allocated vector 'out'
void weave(const char* a, const char* b, char* out, size_t n) {
    uint16_t* ret = (uint16_t*) out;

    for(size_t i = 0; i != n; ++i) {
        ret[i] = weave(a[i], b[i]);
    }
}

// template version, for those that like sugar
template<typename OUT, typename IN>
OUT weave(IN a, IN b, size_t n = 1) {
    OUT out;
    weave((char*) &a, (char*) &b, (char*) &out, sizeof(IN)*n);
    return out;
}

不要忘记在生产代码中添加检查、断言等。

【讨论】:

  • 我不认为这完全符合我的需要。您正在获取两个相同长度的数组并依次交织每个相应的元素。但是,我有一个长度为 n 的数组,我想将所有元素交织在一起。那有意义吗?抱歉不够清楚。
  • 是的,你是对的,我不明白你的问题,我仍然不明白。您能否编辑它以在原始问题下方添加一个说明部分?
猜你喜欢
  • 2010-11-17
  • 1970-01-01
  • 2014-09-25
  • 2012-05-06
  • 2017-06-26
  • 2021-02-13
  • 1970-01-01
  • 2013-09-08
  • 2016-02-20
相关资源
最近更新 更多