让我们说我有一个布尔数组,其中5个布尔变量都为真
bool boo[10];
for(int i = 0; i < 5; i++){
boo[i] = true;
}
我希望将它们全部一次比较成一个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
当我将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
实际上,它不必看起来像上面那样具有正确结果的解决方案。
编辑:非常好的解决方案,谢谢大家
答案 0 :(得分:12)
通过以下方式替换您的定义:
bool NANDGate(bool array[]){
bool at = array[0];
for(int i = 1; i < 5; i++){
at &&= array[i];
}
return !at;
}
not(!
)的末尾必须与!(array[0] && array[1] && array[2] && array[3] && array[4]);
兼容
在您的定义中,您还将两次输入考虑在内
但是直到最后的&&都是没有用的,最好的方法就是这样做:
bool NANDGate(bool array[]){
for(int i = 0; i < 5; i++){
if (!array[i])
return true;
}
return false;
}
答案 1 :(得分:10)
您还可以按如下所示使用std::all_of
并具有良好的可读性:
!std::all_of(std::begin(boo), std::begin(boo)+5, [](bool b){ return b; });
如果要使用此STL函数定义函数bool NANDGate(...)
,则以下实现对您来说很有效:
bool NANDGate(const bool *arr, std::size_t n)
{
return !std::all_of(arr, arr+n, [](bool b){ return b; });
}
GCC和Clang的性能
我通过 Quick C ++ Benchmark 测试了上述函数(标记为std::all_of
)和the accepted答案(标记为Naive
)的性能,同时使用了gcc C ++ 14和O3优化中的-8.2和Clang-7.0。
结果如下。
水平线表示每个布尔数组的大小。
在两个编译器中,对于大于〜8的大小,std::all_of
的性能都比朴素的实现好。
海湾合作委员会(DEMO):
C语(DEMO):
看看GCC的源代码,得出此结果的原因将非常清楚。
std::all_of
的当前GCC实施可以在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);
}
其中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;
}
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;
}
}
尽管我不知道Clang实现的细节,但似乎也可以从上述图表中进行优化。 此外,出于同样的原因,至少在这些编译器中,@ 0x0x5453和@TobySpeight建议的函数也将显示出更好的性能。
答案 2 :(得分:9)
如果您接受C ++ 17解决方案,则可以使用辅助函数和如下模板折叠来制作所有<form class="contact-us" method="post" action="/../contact" name="form_contact" onSubmit="alert('Thank you for your Contacting us');">
<input type="hidden" name="formID_contact" value="609" />
<div style="padding:10px;" class="bg-boxshadow ">
<!-- Text input-->
<div class="row">
<div class="col-xl-4 col-lg-4 col-md-12 col-sm-12 col-12">
<div class="form-group">
<label class="sr-only control-label" for="name">name<span class=" "> </span></label>
<input id="name" name="name" type="text" maxlength="30" placeholder="Name" class="form-control input-md" required>
</div>
</div>
<!-- Select Basic -->
<div class="col-xl-12 col-lg-12 col-md-12 col-sm-12 col-12">
<div class="form-group">
<label class="control-label" for="message"> </label>
<textarea class="form-control" id="message" rows="7" name="message" maxlength="200" placeholder="Message" required></textarea>
</div>
</div>
<!-- Button -->
<div class="col-xl-12 col-lg-12 col-md-12 col-sm-12 col-12">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</div>
</form>
constexpr
如果不能使用C ++ 17,但至少不能使用C ++ 14,则不能使用模板折叠,但是可以在未使用的数组初始化中模拟它;如下
#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;
}
不幸的是,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;
}
和std::index_sequence
仅从C ++ 14开始可用,因此,如果您想要类似的内容,则必须模拟它们(而std::make_index_sequence
不能, C ++ 11,NANDhelper()
)。
答案 3 :(得分:8)
请执行以下操作:
bool NANDGate(bool array[])
{
for(int i = 0; i < 5; i++)
{
if (!array [i])
return true;
}
return false;
}
答案 4 :(得分:4)
使用现代C ++的另一种解决方案:
template <class CONTAINER>
bool NANDGate(const CONTAINER& container) {
auto is_false = [](const auto& item) { return !(bool)item; };
return std::any_of(std::begin(container), std::end(container), is_false);
}
答案 5 :(得分:4)
因为这是C ++,所以我们不需要编写循环。我们可以改用std::any_of
。
如果任何输入为假,我们需要NAND门返回true
:
#include <algorithm>
#include <functional>
bool NANDGate(const bool array[])
{
return std::any_of(array, array+5, std::logical_not<bool>());
}
int main()
{
const bool boo[10] = { true, true, true, true, true };
return NANDGate(boo);
}
答案 6 :(得分:2)
C ++具有std::bitset
,尤其适用于此类情况。使用C ++ 11的干净解决方案:
#include <bitset>
#include <iostream>
const unsigned gateSize = 5;
int main ()
{
std::bitset<gateSize> booBits;
//Set all bits to true by this simple function call...
booBits.set();
//... or some loop
for (unsigned i = 0; i < gateSize; ++i)
booBits[i] = 1;
std::cout << !booBits.all() << std::endl; //This is your NANDgate
}
答案 7 :(得分:1)
如果我使用std::bitset
,很多人都会皱眉,但是有了它,就不需要功能了:
std::bitset<10> boo;
//...
bool boo_nand1= !boo.all();
bool boo_nan2=(~boo).any();