[英]AND Gate with delayed inputs in C#
我正在嘗試實現具有多個輸入的布爾AND門。 每個輸入都有一個標識它的整數。 輸入信號隨機到達,並存儲在門(因此,它不是純AND門,而是具有延遲輸入的門)。 僅當所有輸入信號都到達時,門才會觸發。
注意:到達同一輸入的2個信號不計為2。
我以為我會創建一個字典來存儲輸入,當刺激到達時,更新該特定輸入的Id鍵的值,然后與所有值相加。 如果結果為1,則觸發門並將“字典”的所有“值”重置為0,然后再次等待。
我的方法聽起來有些不對勁,而且我覺得必須有一些更優雅,更高性能(.Net)的東西。
我可能有點不適應,但這看起來似乎Rx Framework很適合。 這樣,您就可以轉到純粹的反應式編程形式,在其中可以聲明在收到所有輸入之前不發送輸出。 對於外部使用者,您的門將充當IObservable<bool>
,這在某種程度上等效於IEnumerable<bool>
。 任何觀察者都只會看到輸出的枚舉,這會延遲接收輸入的方式。
這里的主要好處是您可以鏈接可觀察對象。 因此,如果要將“與”門的輸出鏈接到“或”門的輸入,則可以用一行代碼來完成。 對我而言,Rx是用於建模電路工作方式的理想框架,因為每個可觀察值的結果都在下一個可觀察值的輸入中起作用。
首先,建議您在Channel9上觀看一系列視頻 。
如果輸入ID是順序的,則可以使用bool []代替字典。
bool[] inputs = new bool[10];
void SetInput(int id, bool val)
{
inputs[id] = val;
}
bool trigger()
{
return inputs.All(b => b);
}
void reset()
{
Array.Clear(input, 0, inputs.Length);
}
對我來說,存儲輸入信息似乎是不必要的。 每當信號到達時,只需檢查其是否為零即可確保結果為零。 如果是一個,則不執行任何特定操作。 然后,您只需要檢查是否所有輸入信號都已到達。
編輯:
哦,我現在明白了,用“多個”表示“兩個以上”,並且值沒有整數標識符, 輸入行卻有。 好吧,讓我們重新開始。
您是否真的需要存儲輸入? 如果任何輸入是false
,輸出是false
,所以只要輸出true
,只要你有至少一個(或兩個,如果你喜歡)輸入時true
,直到你得到的輸入是false
。
哦,但是您說“到達相同輸入的兩個信號不算作兩個。” 為了執行此操作,您必須跟蹤(但不必存儲)輸入。 這才是真正的原因。
因此,真正的問題是: 如何在C#中有效地存儲(和檢索)稀疏的整數數組?
當您談論稀疏數組時,無疑會選擇字典(哈希表)。 但是在這種情況下,每個條目只需要一個布爾值,而Dictionary<int, bool>
確實有點浪費。
輸入線路ID的最大范圍是多少? 是[ int.MinValue
, int.MaxValue
]還是更易於管理的范圍? 如果標識符的最大范圍相對較小,則可能需要查看System.Collections.BitArray
或System.Collections.Specialized.BitVector32
。
如果使用這些位集合之一,則有兩種選擇:
bool
值,該值將與每個新輸入相加。 此選項無法將一條線上的false
輸入重置為同一條線上的true
輸入。 假設有32條或更少的輸入行,則上述選項1的有效BitVector32
實現將如下所示:
class AndGate{
BitVector32 activeLines;
BitVector32 inputValues;
public void Reset(){
activeLines[-1] = inputValues[-1] = false;
}
public void Input(int line, bool value){
if(line < 0 || line > 31)
throw new ArgumentOutOfRangeException("line");
activeLines[1 << line] = true;
inputValues[1 << line] = value;
}
public bool GetOutput(bool reset){
bool rtn = activeLines.Data == inputValues.Data;
if(reset)
Reset();
return rtn;
}
}
如果您需要多於32行,則BitArray
的等效實現將是相似的,除了GetOutput
會更復雜且效率更低。 使用BitVector32
或普通int
/ uint
滾動您自己的BitArray
等效項可能更好。
編輯2:
鑒於OP的反對意見,我只能假設期望的行ID位於[ int.MinValue
, int.MaxValue
]中,並且行可以從false
切換為true
。 如果確實如此,那么像我上面概述的那樣密集的實現是不實際的。
現在我們回到Dictionary<,>
。 但是,我們可以對Dictionary<int, bool>
進行一些優化。
一種方法是使用SortedList<,>
。 如果可給予非常大的數目的輸入,一個SortedList<,>
將使用顯著較少的內存比Dictionary<,>
。
例如,在Dictionary<int, bool>
,每個條目將至少使用17個字節的內存。 SortedList<int, bool>
僅使用5。
最大的缺點1是,向SortedList<,>
添加新條目通常比向Dictionary<,>
添加條目要慢得多,因為其鍵值大於所添加條目的其他條目必須向下移動才能為新條目。 我建議使用預期的輸入進行性能分析,以比較SortedList<,>
和Dictionary<,>
之間的內存使用率和CPU占用率。
另一個優化是將我上面提到的BitVector32
方法與Dictionary<,>
/ SortedList<,>
。 這個潛在的 2防止大量浪費的空間存儲8位的布爾值,以及存儲大量的鍵和(如果適用)哈希表開銷。
允許這兩個概念的示例實現如下:
class AndGate{
struct AndEntry{
BitVector32 activeLines;
BitVector32 inputValues;
public bool Output{get{return activeLines.Data == inputValues.Data;}}
public void Input(int line, bool value){
activeLines[1 << line] = true;
inputValues[1 << line] = value;
}
}
IDictionary<int, AndEntry> entries;
public AndGate(bool useSortedList){
if(useSortedList)
entries = new SortedList<int, AndEntry>();
else entries = new Dictionary<int, AndEntry>();
}
public void Reset(){entries.Clear();}
public bool Input(int line, bool value){
AndEntry entry;
entries.TryGetValue(line / 32, out entry);
/* no need to handle the not found case, since AndEntry is a struct */
entry.Input(line & 31, value);
entries[line / 32] = entry;
}
public bool GetOutput(bool reset){
bool rtn = true;
foreach(AndEntry value in entries.Values)
if(!value.Output){
rtn = false;
break;
}
if(reset)
Reset();
return rtn;
}
}
請記住,這些優化的唯一好處是使用更少的內存。 僅當您期望輸入很多時才重要。 確切地說“很多”的含義很難固定下來,但是對於簡單的Dictionary<int, bool>
實現,每個條目都將其稱為20個字節(以解決開銷)。 因此,將您願意使用的內存量除以20。這就是“很多”的意思。 但要注意CPU和內存之間的權衡。
1在有人天真的爭論之前,哈希表上排序列表的真正缺點(這是實現Dictionary<,>
方式)的缺點是排序列表中的查找要比哈希表慢。 他們會說:“但是查找是排序列表中的O(log N),而哈希表中只有O(1)”。 哎呀! 例如,哈希表可能降級為O(N),而排序列表始終為O(log N)。 對於兩個而言,即使您有十億個項目,也不需要花費30整數比較(在這種情況下就是這樣)。 對於哈希表的開銷,許多人驚訝地發現排序后的列表在查找時勝過哈希表的頻率。
2同樣,這取決於您的輸入。 如果lineID & ~31
不經常重疊(因此大多數AndEntry
對象最終只存儲一行),則此解決方案將使用更多的內存,而不是更少。 如果相反,lineID內的其他27個位集傾向於重疊,則Input()
不同掩碼將更有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.