如何在 C++ 中将 10 位映射到 6 位(尽可能高效)?

Posted

技术标签:

【中文标题】如何在 C++ 中将 10 位映射到 6 位(尽可能高效)?【英文标题】:How to map 10 bits to 6 bits in C++ (as efficiently as possible)? 【发布时间】:2011-11-27 11:06:42 【问题描述】:

所以我从功能上知道我想要发生什么,我只是不知道让计算机做到这一点的最佳方法......在 C++ 中......

我想实现一个将 10 位序列映射到 6 位序列的 C++ 函数。

别管这些位现在代表什么...有 2^10 = 1024 种可能的输入。有 2^6 = 64 个不同的输出。应该有很多图案。显然有很多图案。但这很复杂。这是一个已知的映射,只是一个复杂的映射。

输出只是 64 种可能性之一。也许他们都没有习惯。他们可能不会。但假设他们这样做。

现在,我正在考虑一个四重嵌套的 switch 语句,它只处理 1024 个案例中的每一个,并处理内联业务,为指向我传递给此函数的任何结构的任何指针分配适当的值。这似乎很幼稚,而且有点慢。并不是说我已经实现了,但这就是为什么我想先问你。

这个基本功能(映射)必须在每个语句节点上运行,通常不止一次,因为该系统希望支持尽可能多的语句。请问大家,如何在C++中尽可能高效地将10位映射到6位?

我知道映射是什么,我知道哪些 10 位输入与哪些 6 位输出相匹配……我完全可以对它进行硬编码……不知何故?多功能开关太丑了。如何将我的 10 位映射到 6 位?!神经网络?记忆松饼?你会怎么做?

自我说明:这就是我不喜欢查找表的原因。让我们假设所有输入的可能性相同(当然它们不是,并且可以更有效地排序,但仍然如此)然后平均需要 512 个数组的内存推进来检索输出值......似乎如果你让一棵(全局,为什么不)二叉树 10 级深,您可以覆盖 1024 个输入,并且平均只需 10 步即可检索输出……如果有好的模式,可能更少……给定一个确定性函数运行如此频繁,如何最好地从已知输入中检索已知输出?

【问题讨论】:

只使用 & 有什么问题。你不能只做number & 0x3f,它应该只删除第一位。 输入的数据类型是什么?如果它只是一个整数,那么查找表是完美的。如果不是,那么是的,无论如何您都必须进行多达 10 次比较。在这种情况下,它可能与大量 switch 语句的速度相同。但是我无法想象构建一个 1024 入口 switch 语句需要多长时间...... 【参考方案1】:

我会使用包含 1024 个元素的查找表。对它进行硬编码,然后通过索引访问它。

这节省了对大量 switch 语句的需求,并且可能更具可读性。

【讨论】:

所以查找表只是一个将索引 [0-1023] 映射到值 [0-63] 的数组?我只是让它成为全球性的还是什么? 正确。这将是一个全局变量。它可以作为具有 1024 个元素的 char 类型的全局数组来完成。 @Jimmy:是的,只是一个数组(作为元素类型,char 就足够了)。我建议在转换函数中将其设为静态函数,或在定义该函数的文件中设为静态文件。 @Mysticial 滚动可能是个问题。我通常使用它(因为我的编辑器支持折叠,我可以在那里避免它),但在任何情况下我都不会将它设为全局(在可以从另一个翻译单元访问的意义上)。如果没有别的,我会在匿名命名空间中声明它,在文件末尾定义它(从而避免滚动问题)。 @Jimmy:最好避免使用全局变量,但是这里我们讨论的是全局常量,它们是良好编程的基石.您只需要注意定义它们的位置和方式,因为 C++ 不处理初始化/销毁顺序:/【参考方案2】:

取决于你对效率的定义。

    省时:查找表。 节省空间:使用卡诺图。

【讨论】:

卡诺图仍然有 1024 个条目。加上更复杂的代码来访问它。所以它会比简单的数组更节省空间:static char const table[1024] = ... ; 卡诺图是获得简化布尔表达式的工具。因此,理想情况下,您会得到类似 10 个附加项来构建整个表达式并替换 1024 表条目。或者,在最坏的情况下,你会意识到你的整个表是必要的,因为它是不可约的。 @thiton 好的。我以为您的意思是在代码中实现卡诺图。 我认为你们两个有一个伟大的(就像在伟大的工作中,不是很有用)的想法:Boost.Karnaugh!你编写复杂的布尔表达式,boost 在编译时通过训练一个完全在模板元编程中实现的神经网络来简化它,在表达式的真值表上释放它,并以仅仅几个小时的编译时间为代价获得一个简化的表达式,数千小时的时间花在编程这些垃圾上。 :-) 同意,几乎没有足够的 Boost 库需要您手动增加编译器的模板递归深度才能将它们用于最简单的任务。这填补了一个重要的利基市场。【参考方案3】:

使用大小为 1024 的查找表。

【讨论】:

【参考方案4】:

如果您需要映射到某些特定的 6 位值,请在除以 16 后使用 大小为 64(不是 1024!)的查找表。这将适合比 16 倍冗余的 1024 条目表更容易进入缓存(而且,到目前为止,右移的 2 个额外周期超过了可能的缓存未命中的成本)。

否则,如果简单的顺序映射没问题,只需除以 16。

1024/64 = 16,因此除以 16(打开编译器优化的右移)映射到 6 位(顺序)。没有比这更有效的了。

【讨论】:

以上是关于如何在 C++ 中将 10 位映射到 6 位(尽可能高效)?的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中将最低有效位从 int 复制到 long

如何在 Matlab 中将数字四舍五入到 10 个正确的小数位

对于所有外键,如何在 SQL 中将数据类型从 32 位整数升级到 64 位整数?

如何在 C++ 中优雅地格式化字符串,使其四舍五入到小数点后 6 位,并修剪额外的 '0' 或 '9'

在 Spring 中将自动增量 @Id 限制为 6 位

在 MS VC 2013 Express 中将 C++ dll 从 32 位转换为 64 位