Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何快速评估零集?_C++_C_Performance_Sorting_Search - Fatal编程技术网

C++ 如何快速评估零集?

C++ 如何快速评估零集?,c++,c,performance,sorting,search,C++,C,Performance,Sorting,Search,最近的一篇文章询问了在C语言中快速实现以下内容的可能性(假设n是一个无符号整数): if(n==6 | n==8 | n==10 | n==12 | n==14 | n==16 | n==18 | n==20) 一种可能的简化是观察数字a[]={6,8,10,12,14,16,18,20}形成一个,因此移动范围,然后使用一些 if((n-6&14)+6==n) 这将导致一个更短(甚至可能更高效)的实现,正如约翰·博林格(John Bollinger)所言 现在我要问的是,与之类似的优雅(希望同样

最近的一篇文章询问了在C语言中快速实现以下内容的可能性(假设
n
是一个无符号整数):

if(n==6 | n==8 | n==10 | n==12 | n==14 | n==16 | n==18 | n==20)

一种可能的简化是观察数字
a[]={6,8,10,12,14,16,18,20}
形成一个,因此移动范围,然后使用一些

if((n-6&14)+6==n)

这将导致一个更短(甚至可能更高效)的实现,正如约翰·博林格(John Bollinger)所言

现在我要问的是,与之类似的优雅(希望同样高效)的实现是什么

if(n==3 | n==5 | n==11 | n==29 | n==83 | n==245 | n==731 | n==2189)

提示:这次数字
a[k]
形成几何级数:
a[k]=2+3^k


我想在一般情况下,对数字
a[k]
进行排序,然后进行对数搜索,以测试
n
是否是已排序数组的成员。以下是我得出的结论:

bool b;
if (n >= 3 && n <= 2189)
{
    double d = std::log(n - 2)/std::log(3); // log₃(n - 2)
    b = std::trunc(d) == d; // Checks to see if this is an integer
    // If ‘b’ then ‘n == a[log₃(n - 2)]’
}
else b = false;

if (b)
{
    // your code
}
bool-b;

如果(n>=3&&n在相关帖子中发现类似问题: 您可以使用
std::find

bool found = (std::find(my_var.begin(), my_var.end(), my_variable) != my_var.end());
// my_var is a list of elements.
(一定要包括在内)

对于这类东西,99%的情况下,有一个图书馆为你做这项工作

if ((n > 2) && (2187 % (n - 2) == 0))
检查
(n-2)
是否是
3的幂,并且小于或等于
2187
(3到7的幂)

作为推广,要检查任何无符号整数
n
是否是素数
k
的幂,可以检查
n
是否除以可存储在无符号整数中的
k
的最大幂

提示:这次数字
a[k]
形成几何级数:
a[k]=2+3^k

函数定义为
isPow(x,y)

同样,我们可以扣除
k

int k = findK(n-2, 3);

int findK(unsigned long x, unsigned int y)
{
    unsigned int k = 0;

    while (x % y == 0)
    {
        x /= y;
        k++;
    }

    if (x == 1) return k;
    else return (-1);
}

n - 2 = 3 * 3^(k-1)       for k > 0
(n - 2) / 3 = 3^(k-1)
(n - 2) / 3 / 3 = 3^(k-2)
(n - 2) / 3 / 3 / 3 = 3^(k-3)
(n - 2) / 3 / 3 / 3 / 3 = 3^(k-4)
..
(n - 2) / 3 / 3 / ..i times = 3^(k-i)
..
(n - 2) / 3 / 3 / ..k times = 3^0 = 1

做这类事情的一个非常有效的方法是使用一个集合,特别是一个。作为一个哈希表,搜索是平均常数,最差线性的。它也比一系列条件和比例优雅得多

只需插入要比较的值,然后对集合中的值进行计数。如果找到,则它是您测试的值之一

std::unordered_set< int > values;
values.insert( 3 );
values.insert( 5 );
values.insert( 11 );
values.insert( 29 );
values.insert( 83 );
values.insert( 245 );
values.insert( 731 );
values.insert( 2189 );

...

if( values.count( input ) )
    std::cout << "Value is in set.\n";
else
    std::cout << "Value is NOT in set.\n";
std::无序_集值;
插入(3);
插入(5);
插入(11);
插入(29);
插入(83);
插入(245);
插入(731);
插入(2189);
...
if(值.计数(输入))
std::cout这与非常相似,您可以进行调整,例如:

bool测试(无符号x){
x-=2;
如果(x>2187)
返回0;
如果(x>243)
x*=0xd2b3183b;

返回x如果这是一个时间与空间的折衷,那么我将分配一个2189字的缓冲区,除了特定的位置(3、5、11等等)之外,它将填充零,并简单地执行数组查找(这是非常快的,因为它是硬件实现的)。这不是很优雅,但会以空间性能为代价给你带来最佳的时间性能。这样的问题不应该发布在?FWIW上吗?
((n-6)和14)+6==n
可以简化为
(n-6)| 14==14
@UriBrecher-可能是2k值。对于一般情况,庞大的查找表对缓存的影响可能是不可忽略的。您是追求原始速度还是优雅的C代码?它们可能不同。除法(包括模)操作是现代处理器上最慢的操作,所以Suu的答案看起来很酷,但可能不会比一系列的比较快。如果你真的关心速度,那么在决定之前检查你的编译器的输出和基准。也考虑到分支在紧循环中是慢的。如果你的优化器不是SM。艺术足以自动完成这个替换(Clang是,其他不是),考虑使用位或代替逻辑或。如果“代码> n<2</代码>BTW,计算单个<代码>日志< /代码>可能比原始表达式多。至少对于<代码>日志(3)
,因为问题是关于性能的,所以您可能应该在
静态变量中维护它(即,只计算一次)@barakmanos谢谢我修复了它。嗯,我没想到,也许我会测试它…再想想,
log
可能返回
-inf
of
NaN
,在这种情况下,接下来的测试可能会起作用。
静态双log3=std::log(3)
。为什么在没有优化的情况下对其进行测试?这几乎让我们无法确定哪一个更快。
std::find
具有线性运行时。我认为这算不上可能的最快实现……对于8个值,这可能很快-许多CPU都有一个带计数器的重复比较操作来限制性能数据量的搜索,它没有太多的数据缓存。如果这比二进制搜索更让我吃惊。@ TonyD,我认为在一个C++会议上有一个演示,在这里,它实际上是被测量的,而对于小的集合来说,线性搜索更快。然而,这个问题也要求一般的情况,他正在计算。汇编程序指令。在这种人工情况下,我认为线性搜索不符合条件。@Matsmath在这个专业中,我们是用事实而不是感情来操作的。@Matsmath为什么包含库会影响性能?函数调用可能还是内联的。性能不会与手写循环不同。这是一个很好的answ呃,但是你应该把“小于或等于2187”改为“小于或等于2189”。另外,你应该添加一个
n>2
@thiru很棒的工作!(我可以通过测试确认你的解决方案是正确的,而且速度更快(1.14703纳秒,而不是3.34201纳秒)。注意除法运算(包括模运算)基本上是现代处理器上最慢的指令,速度要慢得多
int k = findK(n-2, 3);

int findK(unsigned long x, unsigned int y)
{
    unsigned int k = 0;

    while (x % y == 0)
    {
        x /= y;
        k++;
    }

    if (x == 1) return k;
    else return (-1);
}

n - 2 = 3 * 3^(k-1)       for k > 0
(n - 2) / 3 = 3^(k-1)
(n - 2) / 3 / 3 = 3^(k-2)
(n - 2) / 3 / 3 / 3 = 3^(k-3)
(n - 2) / 3 / 3 / 3 / 3 = 3^(k-4)
..
(n - 2) / 3 / 3 / ..i times = 3^(k-i)
..
(n - 2) / 3 / 3 / ..k times = 3^0 = 1
std::unordered_set< int > values;
values.insert( 3 );
values.insert( 5 );
values.insert( 11 );
values.insert( 29 );
values.insert( 83 );
values.insert( 245 );
values.insert( 731 );
values.insert( 2189 );

...

if( values.count( input ) )
    std::cout << "Value is in set.\n";
else
    std::cout << "Value is NOT in set.\n";
bool test(unsigned x) {
    x -= 2;
    if (x > 2187)
        return 0;
    if (x > 243)
        x *= 0xd2b3183b;
    return x <= 243 && ((x * 0x71c5) & 0x5145) == 0x5145;
}
bool test2(unsigned x) {
  x -= 2;
  return x <= 2187 && (((x * 0x4be55) & 0xd2514105) == 5);
}