将多个(离散)操作折叠为一个(连续)操作

时间:2013-05-09 19:22:53

标签: c math optimization discrete-mathematics

举一个简单的例子,假设我们正在检查char c是否是字母数字:

if (48 <= c && c <= 57 ||
    65 <= c && c <= 90 ||
    97 <= c && c <= 122)
{
    // ...
}

确认 的6次操作。

但是,不存在连续函数 f(c),使得 f(c)&gt; 0 表示字母数字字节值,&lt; 0 其余的?我认为 至少有一个:12度的多项式,“适合”12个点,在x轴上下编织;但也许存在较小程度的函数,甚至非多项式。这样的公式将“简化”操作:

if (f(c) > 0)
{
    // ...
}

这是否有艺术术语?(想到“折叠”这个词,但它不会产生任何相关的搜索结果 - 只有Haskell的折叠概念。)似乎只要我们可以将一组操作的codomain映射到具有足够精细粒度的codomain,我们就可以获得这样的“折叠”。那么我的问题是:可以“折叠”节省时间吗?或者是否有一些保护原则会迫使计算“折叠”的成本与计算成本相匹配(甚至超过)原始的“原油”操作。

3 个答案:

答案 0 :(得分:6)

多项式与x轴相交6次,即它有6个实根,因此6次多项式就足够了。

f(c) = -(c-48)*(c-57)*(c-65)*(c-90)*(c-97)*(c-122)
     

enter image description here

这当然会浪费时间,做5次乘法比5次逻辑操作慢得多。此外,&&||是短路的,因此您通常无需执行所有这些操作。

答案 1 :(得分:4)

在您的特定情况下,最佳形式是:

unsigned u = c;
if (u-48<10 || (u|32)-97<26)

当然,这并没有解决你所期待的问题,而是相同的概念(即(1)将一个范围的两个比较转换为一个无符号减法和比较,以及(2)使用按位 - 或组合多个长度相同且对齐匹配的范围检查通常可以推广到其他情况。

答案 2 :(得分:2)

是否有某些原因使isalnum()函数不足以满足您的需求?不要忘记#include <ctype.h>