只要数组C++,就可以在一个语句中比较布尔变量

Has*_*ase 13 c++ boolean-logic c++11

假设我有一个布尔数组,其中5个bool变量都为真

bool boo[10];
for(int i = 0; i < 5; i++){
    boo[i] = true;
}
Run Code Online (Sandbox Code Playgroud)

我希望它们一次比较到一个NAND逻辑门,因为我的问题是如果我总是比较两个变量并将合并的布尔值与i + 1布尔变量进行比较.这给出了错误的结果.

    bool NANDGate(bool array[]){
    bool at;
    for(int i = 1; i < 5; i++){
        if(i == 1){
            at = !(array[i-1] && array[i]);
        }else{
            at = !(at && array[i]);
        }
    }
    return at;
}
// result here is true even though it should be false
Run Code Online (Sandbox Code Playgroud)

当我将每个变量从boo放入NAND门时,我想要的是一个正确的结果,所以这可能是这样的:

bool func(bool array[]){
// some loop
result = !(array[0] && array[1] && array[2] && array[3] && array[4]);
return result;
}
// result here would be false
Run Code Online (Sandbox Code Playgroud)

实际上它不必看起来像是一个像上面那样具有正确结果的解决方案.

编辑:这么多很棒的解决方案我都感谢你们

bru*_*uno 12

替换你的定义:

 bool NANDGate(bool array[]){
   bool at = array[0];
   for(int i = 1; i < 5; i++){
     at &&= array[i];
   }
   return !at;
 } 
Run Code Online (Sandbox Code Playgroud)

not(!)必须在最后才能兼容!(array[0] && array[1] && array[2] && array[3] && array[4]);

在您的定义中,您还会考虑一些条目2次

但要做到&&直到最后是没用的,最好的只是做:

 bool NANDGate(bool array[]){
   for(int i = 0; i < 5; i++){
     if (!array[i])
       return true;
   }
   return false;
 } 
Run Code Online (Sandbox Code Playgroud)


Hir*_*oki 10

您还可以使用std::all_of以下良好的可读性:

DEMO

!std::all_of(std::begin(boo), std::begin(boo)+5, [](bool b){ return b; });
Run Code Online (Sandbox Code Playgroud)

如果要bool NANDGate(...)使用此STL函数定义函数,那么以下实现对您有用:

DEMO

bool NANDGate(const bool *arr, std::size_t n) 
{
    return !std::all_of(arr, arr+n, [](bool b){ return b; });
}
Run Code Online (Sandbox Code Playgroud)

GCC和Clang的表现

我测试上述功能(标记为的性能std::all_of)和所接受的回答(标记为Naive)通过快速C++基准用gcc-8.2和锵-7.0在C++ 14和O3优化两者.结果如下.水平线表示每个布尔数组的大小. 在两个编译器中,std::all_of对于大于~8的大小,显示出比天真实现更好的性能:

GCC(DEMO):

在此输入图像描述

Clang(DEMO):

在此输入图像描述

看一下GCC的源代码,这个结果的原因会很清楚.当前的GCC实现std::all_of可以在gcc/libstdc ++ - v3/include/bits/stl_algo.h中看到,其中包括:

template<typename _InputIterator, typename _Predicate>
inline bool
all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred)
{ 
    return __last == std::find_if_not(__first, __last, __pred);
}
Run Code Online (Sandbox Code Playgroud)

其中std::find_if_not也使用函数在同一文件中实现__find_if.请注意,有两个重载__find_if.第一个是非常简单的一个:

template<typename _InputIterator, typename _Predicate>
inline _InputIterator
__find_if(_InputIterator __first, _InputIterator __last,
          _Predicate __pred, input_iterator_tag)
{
    while (__first != __last && !__pred(__first))
        ++__first;

    return __first;
}
Run Code Online (Sandbox Code Playgroud)

OTOH,第二个是随机访问迭代器的重载函数,并针对它们进行了优化. 实施如下.由于随机访问迭代器的距离可以用常数复杂度O(1)快速计算,因此这种手动循环展开可以有效地工作.在我们当前的情况下,boo是一个原始指针,它是一个随机访问迭代器.因此调用了这种优化的过载函数.这应该是为什么std::all_of表现出比几乎所有尺寸的朴素实现更好的性能:

DEMO(RAI ver.被称为)

/// This is an overload used by find algos for the RAI case.
template<typename _RandomAccessIterator, typename _Predicate>
_RandomAccessIterator
__find_if(_RandomAccessIterator __first, _RandomAccessIterator __last,
          _Predicate __pred, random_access_iterator_tag)
{
    typename iterator_traits<_RandomAccessIterator>::difference_type __trip_count = (__last - __first) >> 2;

    for (; __trip_count > 0; --__trip_count)
    {
       if (__pred(__first))
           return __first;

       ++__first;

       if (__pred(__first))
           return __first;

       ++__first;

       if (__pred(__first))
           return __first;

       ++__first;

       if (__pred(__first))
           return __first;

       ++__first;
    }

    switch (__last - __first)
    {
    case 3:
      if (__pred(__first))
          return __first;

      ++__first;
    case 2:
      if (__pred(__first))
          return __first;

      ++__first;
    case 1:
      if (__pred(__first))
          return __first;

      ++__first;
    case 0:
    default:
      return __last;
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然我不知道Clang实现的细节,但似乎也可以从上面的图中进行优化.此外,出于同样的原因,@ 0x0x5453和@TobySpeight提出的函数至少在这些编译器中也会表现出更好的性能.


max*_*x66 9

如果您接受C++ 17解决方案,则可以constexpr使用辅助函数和模板折叠完成所有操作,如下所示

#include <iostream>
#include <utility>
#include <type_traits>

template <std::size_t N, std::size_t ... Is>
constexpr bool NANDhelper (bool const (&a)[N],
                           std::index_sequence<Is...> const &)
 { return ! (a[Is] && ...); }

template <std::size_t N>
constexpr bool NANDgate (bool const (&a)[N])
 { return NANDhelper(a, std::make_index_sequence<N>{}); }

int main ()
 {
   bool a[] { true, true, true, true, true };
   bool b[] { true, false, true, true, true };

   std::cout << NANDgate(a) << std::endl;
   std::cout << NANDgate(b) << std::endl;
 }
Run Code Online (Sandbox Code Playgroud)

如果您不能使用C++ 17,但至少使用C++ 14,则不能使用模板折叠,但可以在未使用的数组初始化中模拟它; 事情如下

template <std::size_t N, std::size_t ... Is>
constexpr bool NANDhelper (bool const (&a)[N],
                           std::index_sequence<Is...> const &)
 {
   using unused = bool[];

   bool val { true };

   (void)unused { true, (val &= a[Is])... };

   return ! val; 
 }
Run Code Online (Sandbox Code Playgroud)

不幸的是std::index_sequence,std::make_index_sequence它只能从C++ 14开始提供,因此,如果你想要类似的东西,你必须模仿它们(并且NANDhelper()不能,在C++ 11中constexpr).


Pau*_*ers 8

以下应该这样做:

bool NANDGate(bool array[])
{
    for(int i = 0; i < 5; i++)
    {
        if (!array [i])
            return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)