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以下良好的可读性:
!std::all_of(std::begin(boo), std::begin(boo)+5, [](bool b){ return b; });
Run Code Online (Sandbox Code Playgroud)
如果要bool NANDGate(...)使用此STL函数定义函数,那么以下实现对您有用:
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表现出比几乎所有尺寸的朴素实现更好的性能:
/// 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提出的函数至少在这些编译器中也会表现出更好的性能.
如果您接受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).
以下应该这样做:
bool NANDGate(bool array[])
{
for(int i = 0; i < 5; i++)
{
if (!array [i])
return true;
}
return false;
}
Run Code Online (Sandbox Code Playgroud)