我经常需要比较两个位数组以查看它们是否相同,所以我找到了一个对我来说看起来不太合适的函数,看起来它可能更好,因为有三个逻辑运算在一条线上。我很想知道它是否可以简化它。
Public Overloads Shared Function AreEqual(ByVal ba1 As BitArray, ByVal ba2 As BitArray) As Boolean
If ba1.Length <> ba2.Length Then
Return False
End If
Dim i As Integer
For i = 0 To ba1.Length - 1
If Not (Not ba1(i)) Xor ba2(i) Then
Return False
End If
Next
Return True
End Function
修改
经过几个小时的测试和头脑风暴后,我开始考虑减少这三个逻辑运算符的数量,并将其中一个放入变量中,这意味着一次性恢复所有位而不是一点一点地恢复。这是结果,并且比前一个快得多,大约快3倍:
Public Overloads Shared Function AreEqual(ByVal ba1 As BitArray, ByVal ba2 As BitArray) As Boolean
If ba1.Count <> ba2.Count Then
Return False
End If
Dim revBa1 As BitArray = ba1.Not ' <<
Dim i As Integer
For i = 0 To ba1.Count - 1
If (Not revBa1(i)) Xor ba2(i) Then ' eliminates one logical operation existing here before
Return False
End If
Next
Return True
End Function
现在,比这更快? :)谁知道,也许......
编辑2:
经过一些更多的测试和不确定的结果后,我注意到该函数的第二个版本是不正确的。虽然它得到了正确的结果,但它改变了ba1值,就像它通过函数传递给函数一样:
'------------------------
'ba1 before = 000000000000000000000000000000001
'ba2 before = 000000000000000000000000000000001
'ba1 after = 111111111111111111111111111111110
'ba2 after = 000000000000000000000000000000001
'function result = True
'------------------------
有什么想法吗?
编辑3: 解决方案很简单,但功能不再快:
Dim revBa1 As New BitArray(ba1)
revBa1 = revBa1.Not()
编辑4: 是的,就是这样:
Public Overloads Shared Function AreEqual(ByVal ba1 As BitArray, ByVal ba2 As BitArray) As Boolean
If ba1 Is Nothing OrElse ba2 Is Nothing Then
Return False
End If
If ba1.Count <> ba2.Count Then
Return False
End If
Dim i As Integer
For i = 0 To ba1.Count - 1
If ba1(i) Xor ba2(i) Then
Return False
End If
Next
Return True
End Function
我猜有时我们不会因为树木而看不到森林:)
答案 0 :(得分:1)
class Cartesian{
public:
double x() const { return r_(0); }
double y() const { return r_(1); }
double z() const { return r_(2); }
std::vector<double> const& r() const { return r_; };
Cartesian* operator=(std::vector<double> const& r) {r_ = r;}
private:
std::vector<double> r_;
//Eigen::Array3d r_;
};
// Send vector of Cartesian
void sendData(std::vector<Cartesian> const& v) {
std::vector<double> data;
for (auto const& i : v) {
data.insert(data.end(), v.r().begin(), v.r().end());
}
MPI_Send(data.begin(), data.size(), MPI_DOUBLE, 0, 1, MPI_COMM_WORLD);
}
// Receive vector of Cartesian
std::vector<Cartesian> recvData() {
int n;
MPI_Status status;
MPI_Probe(0, 0, MPI_COMM_WORLD, &status); // Incoming?
MPI_Get_count(&status, MPI_INT, &n); // Number of incoming
std::vector<Cartesian> v;
if (n>0) {
std::vector<double>(n);
MPI_Recv(n.begin(), n, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
v.resize(n/3);
int i = 0;
for (auto i : v) {
i.r(*b.begin()+3*i);
++i;
}
}
return v;
}
int main() {
MPI_Init(NULL, NULL);
int size, rank;
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
std::vector<Cartesian> data;
if (rank == 0) {
data.resize(1000);
sendData(data);
} else {
data = recvData();
}
MPI_Finalize();
}
和ba1(i)
返回可以直接比较的布尔值:
ba2(i)
Function AreEqual(ba1 As BitArray, ba2 As BitArray) As Boolean
If ba1.Count <> ba2.Count Then Return False
For i = 0 To ba1.Count - 1
If ba1(i) <> ba2(i) Then Return False
Next
Return True
End Function
使用Integer array to store the bits,因此对于更大的BitArray(可能大约100位?你可能需要测试它),在比较之前将它们复制到整数数组可能会快一点:
BitArray
作为旁注,比较可枚举集合的越来越慢的方法是SequenceEquals
:
Function AreEqual(ba1 As BitArray, ba2 As BitArray) As Boolean
If ba1.Count <> ba2.Count Then Return False
If ba1.Count < 64 Then ' needs some testing to determine this number
For i = 0 To ba1.Count - 1
If ba1(i) <> ba2(i) Then Return False
Next
Else
Dim a1 = New Integer((ba1.Length - 1) \ 32) {}
Dim a2 = New Integer((ba2.Length - 1) \ 32) {}
ba1.CopyTo(a1, 0)
ba2.CopyTo(a2, 0)
For i = 0 To a1.Length - 1
If a1(i) <> a2(i) Then Return False
Next
End If
Return True
End Function