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

时间:2020-08-01 20:14:50

标签: c++ c

假设我有一堆整数(10〜20),需要检查它们是否等于0。最有效的方法是什么?我不想评估一个巨大的if(a = 0 || b = 0 || c = 0 || ...)语句。我想到过if(a b c ... = 0),但是如果我没记错的话,乘法并不是一个非常快的过程。还有其他技巧,例如按位操作会起作用吗?我正在尝试尽可能降低级别,以使此超级高效。

4 个答案:

答案 0 :(得分:3)

我很确定最快,最清晰的方法是使用显式测试:

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

由于||&&是C中的短路运算符,因此一旦知道最终结果,评估就会立即停止,因此,例如b变量为零,该表达式满足true并停止对其余表达式的求值。

@AbhayAravinda建议!(a && b && c && d ...)可能会更有效,但我不这么认为。因为这不是执行显式的not操作,而是针对零的低级别测试,所以对于几乎​​所有可靠地执行的体系结构来说,这都是一个非常容易的测试。我快速浏览了两个版本的优化汇编程序,但没有明显的性能赢家,但我认为第一个版本更清晰。

如果每个周期都很重要,那么请检查平台上的两个版本,但是在我的64位Intel系统上,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文件。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

大多数人给出的答案如下:

!a || !b || ...

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

这样的想法是,在a为零的情况下,将不评估序列的其余部分(由于不必要),这是编译器执行的一种优化。

这使问题变成了:您的编译器是否执行了此优化(如果是“可能的话”,执行此优化的参数是什么)?

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

答案 3 :(得分:0)

您可能会看到汇编器输出。

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

也许更好的确定性解决方案是使用按位AND运算符。如果一个操作数为0,则结果将为0。所以类似:

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

将为每个变量生成一个mov,然后是and语句。

因此,如果为0的变量位于if语句的后半部分,则bitweise AND将更快。

相关问题