簡體   English   中英

數組中所有元素之間的邏輯運算

[英]Logical operation between all elements in array

我想以最有效的方式使用布爾運算符比較數組中的所有項目。 目前,我有這樣的事情:

bool myFunction(int i) 
{

    bool *myArray = {true, true, false, false, true};
    //suppose we know that i = 5 and that i is the length of the array...
    return myArray[0] && myArray[1] && myArray[2] && myArray[3] && myArray[4];
}

由於數組的大小不是固定的,因此'i'的值可以更改,而我的return語句將不再起作用,因此我必須實現這樣的內容

bool myFunction(int i) 
{
    bool *myArray = //some other array of bools
    //should work with any value of i
    bool result = myArray[0];
    for (int a = 1; a < i; ++a)
    {
        result &= myArray[i];
    }
    return result;
}

我想知道是否有更好的方法,而不是進行for循環並遍歷每個元素,然后將列表中下一項的值與前兩項的存儲結果進行比較。 就像一些按位運算符可以使此操作變得容易一樣,任何東西都可以消除循環。

您可以使用boost::dynamic_bitset ,它具有成員函數any() ,如果設置了該位集中的任何位,該函數將返回true 如果未設置任何位,則none()將返回true

但是any()的實現是:

template <typename Block, typename Allocator>
bool dynamic_bitset<Block, Allocator>::any() const
{
    for (size_type i = 0; i < num_blocks(); ++i)
        if (m_bits[i])
            return true;
    return false;
}

因此,您有一個for循環!

但是,如果您正在搜索諸如並行計算之類的東西,則可能要使用arrayfire :例如,它具有執行此操作的算法

template<typename T >
T af::allTrue(  const array &   in  )   
//C++ Interface for checking if all values in an array are true.

您可能需要知道&=不是邏輯運算符; 它是“按位與”運算符。 只要您僅在布爾值上使用它,我想它就可以正常工作。 但是C不會阻止1或0以外的其他值滑入數組,因此您可能不應該做這個假設。 從語義上來說,如果您正在做邏輯運算,或者您想用&&代替&

也就是說,您當然可以使用短路來完善您正在做的事情。 一旦找到單個0(假),此后的任何事情都不會使聚合返回1(真),因此您最好停止。

for (int a = 1; result && a < i; ++a)
{
    result &= myArray[i];
}

除此之外,您沒有什么可以改善的地方。 不知道為什么不喜歡循環,但是如果您想組合未知數量的值,則必須進行迭代。 您可能會找到(或編寫)一些實用程序函數來執行此操作,但是無論如何它都會在內部使用循環。 (除非它試圖利用向量處理器本來可以執行您想要的操作,也許……但是那將是毫無意義的,並且,如果您確實沒有值的數量限制,那么仍然會涉及到循環。)

一旦遇到false ,就可以退出循環:

for (int a = 0; a < i; a++)
{
    if (!myArray[i])
        return false;
}
return true;

如果允許您更改數組中的最后一個值,則可以使用以下技巧進行優化:

  • 如果數組中的最后一個值為false ,則返回false
  • false寫入數組的最后一個條目
  • 迭代數組,直到遇到false
  • true寫入數組的最后一個條目
  • 如果您最后輸入之前停止,則返回false
  • 返回true

編碼:

int a;
if (!myArray[i-1])
    return false;
myArray[i-1] = false;
for (a = 0; a < i; a++)
{
    if (!myArray[i])
        break;
}
myArray[i-1] = true;
return a != i-1;

每次迭代產生一個分支,而不是每次迭代產生兩個分支。


如果允許您分配i+1條目,則可以擺脫“最后一個條目交換”部分:

int a;
myArray[i] = false;
for (a = 0; myArray[i]; i++);
return a != i;

您還可以擺脫myArray[i]嵌入的其他算法:

bool *arrayPtr;
myArray[i] = false;
for (arrayPtr = myArray; *arrayPtr; arrayPtr++);
return arrayPtr != myArray+i;

如果編譯器尚未應用它,那么此函數將確定會應用。 另一方面,這可能會使優化程序更難展開循環,因此您必須在生成的匯編代碼中進行驗證...

您可以使用all_of (如果要檢查整個數組而不是第一個i元素,請用std::end(myArray)替換std::begin(myArray) + i ):

#include <vector>
#include <algorithm>
bool myFunction(int i)
{
    std::vector<bool> myArray = { true, true, false, false, true };
    return std::all_of(std::begin(myArray), std::begin(myArray) + i, [](bool elem) { return elem; });
}

我會更改for循環的條件,因此,如果遇到錯誤的值並使用迭代器而不是索引,則不會繼續。

bool myFunction(int i) {
    bool myArray[i] = //some other array of bools
    //should workwith any value of i

    bool result;
    bool * a;
    for (a = myArray, result = *a; a < myArray+i && result; result=*(++i)) {}
    //no need to use the AND operator since we stop if we meet one false

    return result;
}

或者,如果您真的更喜歡使用index:

bool myFunction(int i) {
    bool myArray[i] = //some other array of bools
    //should workwith any value of i

    bool result;
    unsigned int a;
    for (a = 0, result = myArray[a]; a < i && result; result=myArray[++i]) {}
    //no need to use the AND operator since we stop if we meet one false

    return result;
}

也許我是錯的,但是如果不在位范圍操作上,我就不會使用按位AND賦值(&=),盡管它與布爾類型實際上並不相關。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM