检查给定的一组整数是否包含0值

  • 本文关键字:整数 一组 是否 包含 c++ c
  • 更新时间 :
  • 英文 :


假设我有一堆整数(10~20(,需要检查其中是否有一个等于0。最有效的方法是什么?我不想评估一个巨大的if(a=0||b=0||c=0||…(语句。我想过如果(abc…=0(,但如果我没记错的话,乘法不是一个很快的过程。还有其他技巧吗,比如位操作?我试着尽可能低水平地思考,以使这项工作超高效。

我确信最快、最清晰的方法是使用显式测试:

int has_zero = !a || !b || !c || !d || !e ...;

因为||&&是C中的短路运算符,一旦知道最终结果,求值就会停止,所以如果(例如(b变量为零,则满足表达式为真,并停止求值其余部分

@AbhayAravinda认为!(a && b && c && d ...)可能更有效,但我不这么认为;因为这与其说是做一个显式的not操作,不如说是一个针对零的低级别测试,所以对于几乎任何架构来说,这都是一个非常容易可靠的测试。我快速查看了两个版本的优化汇编程序,在性能方面没有明显的赢家,但我认为第一个版本更清晰。

如果每个周期都很重要,那么在您的平台上检查这两个版本,但在我的64位英特尔系统上,gcc和clang实际上为两个版本生成了相同的程序集(启用了优化(。

简单测试代码:

int a, b, c, d, e, f;
int test_or()
{
return !a || !b || !c || !d || !e || !f;
}
int test_and()
{
return ! (a && b && c && d && e && f);
}

int main()
{
return test_or() | test_and();
}

使用gcc -S -O testfile.c编译此文件,然后查看生成的.s文件。

依次测试每一个。利用||短路特性;按照每个变量为零的概率降序排列:

if (!a/*most likely to be zero*/ || !b || ...){
// one of them is zero
}

大多数人给出的答案是:

!a || !b || ...

(其中a是最有可能为零的一个(

其思想是,如果a为零,则不计算序列的其余部分(因为没有必要(,这是一种由编译器执行的优化。

这就把问题变成了:你的编译器是否执行这种优化(在"可能是"的情况下,为了强制执行这种优化,参数是什么(?

你能告诉我们你正在使用哪个编译器(版本(吗?这可能使我们能够验证这一点。

您可以查看汇编程序的输出。

!a || !b || !c || !d || !e || !f将为您提供一堆cmpje语句。每个变量一对。由于布尔快捷求值,它可能运行得非常快。或者不是。

可能更好且具有确定性的解决方案是使用逐位and运算符。如果一个操作数为0,则结果将为0。有点像:

if (a & b & c & d & e & f & g & h & i & j & k)

将为每个变量生成一个CCD_ 13语句,然后生成CCD_。

因此,如果变量0在if语句的后半部分,那么位与将更快。

最新更新