如何改进一堆在已知值范围内评估变量的 else-if 条件?
How to improve a bunch of else-if conditions that evaluate a variable inside a range among known values?
有没有办法将下面的代码转换为更具可扩展性的代码?我已经简化了它,但我真正的必须检查几个不同的值,并且它要求重构。
if (x < 0) foo1();
else if (x < 3) foo2();
else if (x < 8) foo3();
else foo4();
我尝试了以下方法:
struct Ptr2foo {
void (*foo_x)();
}
Ptr2foo ptr2foo_x[4] {
foo1,
foo2,
foo3,
foo4
}
ptr2foo_x[someMagicWithMy_X_AndMyKnownValues].foo_x();
这些值在编译之前是已知的,循环内的条件数量正在降低性能。
这是解决此问题的最佳方法吗?高度赞赏任何带有其解释的替代解决方案
在一般情况下,你有一些区间[a1, a2), [a2, a3), ..., [an, infty)
并且想要找到x
所在的区间,你可以使用最坏情况log n
比较(相对于具有最坏情况n
比较的if-else链(。您可以通过对间隔进行二叉搜索来做到这一点。因此,您将首先检查x
是否小于a(n/2)
,然后进一步检查if
情况下较小的间隔和else
情况下较大的间隔。对于上面的示例,转换
if (x < 0) foo1();
else if (x < 3) foo2();
else if (x < 8) foo3();
else foo4();
在它的最长
路径上有 4 个比较,在最短路径上有 1 个比较if( x < 3 ) {
if( x < 0 ) foo1();
else foo2();
} else {
if( x < 8 ) foo3();
else foo4();
}
这在其所有路径上都有 2 个比较。
请注意,在最坏的情况下,较少的比较不一定更快。如果x
大致均匀分布,则速度更快。如果x
在 90% 的情况下为负数,您的第一个版本会更快,因为它大多只使用一个比较,而我的版本始终使用 2。
这就是为什么您还应该考虑通过此代码的热路径(即最常见的路径(是什么。如果在大多数情况下x
至少是 8,您绝对应该先检查它,依此类推。
您可以使用interval_map
.这里有一个示例实现 简单地说,它包含设定范围内任何内容的引用。 您需要填充案例的边缘情况,例如:
m_map.insert(std::make_pair(0, foo1));
m_map.insert(std::make_pair(3, foo2));
m_map.insert(std::make_pair(8, foo3));
然后你可以简单地得到你想要的函数m_map[1]
. 这将返回映射中的第一个函数。
注意:我给出链接作为示例。实施可能存在问题。您最好在使用前对其进行测试。
相关文章:
- 为什么在全局范围内使用"extern int a"似乎不行?
- 错误:未在此范围内声明'reverse'
- 并行用于C++17中数组索引范围内的循环
- 求出有多少个数字是完美平方,而sqrt()是L,R范围内的素数
- 不计算一个范围内的完美数
- 错误:"imread"未在此范围内声明
- 我在范围内未声明的错误类有问题
- 如何在cpp中使用地图显示给定日期范围内(在下面的问题中)的费率?
- 我有一个数组,我想输入一个范围,然后找到范围内所有偶数的总和?
- 未在此范围内声明错误 'xy'
- 在C++中使用变量而不是"#define"来指定数组大小是不是一种糟糕的做法?(C错误:在文件范围内
- 命名空间范围内的外部 - GCC vs clang vs msvc
- 如何改进一堆在已知值范围内评估变量的 else-if 条件?
- 如何仅使用 While 循环在给定范围内找到可被 7 整除的计数整数
- Socklen_t未在此范围内声明
- 错误:'[' 之前预期的非限定 id 和错误:'users'未在此范围内声明
- 查找给定范围内最长连续 1 的频率
- "Main"已在当前范围内声明
- c++ 变量在宏的扩展中没有在这个范围内声明
- 变量不在 lambda 的范围内