按行、列或随机从数组填充矩阵时出现错误索引问题
Bad index issues while populating a matrix from an array by rows, columns or randomly
让你有一个包含 n
元素的 std::vector< T >
(T
我的意思是任何 class 或类型名称)并且你想要填充一个类似矩阵的对象,例如 class boost::numeric::ublas::matrix< T >
的对象,其维度为 m1
行和 m2
列,逐行或逐列逐个插入这些元素。
首先,它必须是 n <= m1 * m2
或者我们试图用 11 个或更多元素填充,比方说,10 个槽位;然后:如果n <= m1
(分别为n <= m2
)循环就足够了。
但是如果 n > m1
(n > m2
) 你必须拆分你的 std::vector< T >
以避免糟糕的索引问题并根据你的选择填充你的矩阵。
这是我的尝试:
#include <algorithm>
#include <boost/numeric/ublas/matrix.hpp>
#include <vector>
template < class T > inline void PopulateGrid(const std::vector< T >& tVector,
boost::numeric::ublas::matrix< T >& tMatrix,
char by = 'n')
{
if (tVector.size() > tMatrix.size1() * tMatrix.size2())
throw("Matrix is too small to contain all the array elements!");
else
{
switch(by)
{
case 'r' :
for (unsigned i = 0; i < tMatrix.size1(); i++)
{
for (unsigned j = 0; j < tVector.size(); j++)
{
if (j <= tMatrix.size2())
tMatrix(i, j) = tVector[j];
else
tMatrix(i + 1, j - tMatrix.size2()) = tVector[j];
}
}
break;
case 'c' :
for (unsigned j = 0; j < tMatrix.size2(); j++)
{
for (unsigned i = 0; i < tVector.size(); i++)
{
if (i <= tMatrix.size1())
tMatrix(i, j) = tVector[i];
else
tMatrix(i - tMatrix.size1(), j + 1) = tVector[j];
}
}
break;
default:
for (unsigned i = 0; i < tMatrix.size1(); i++)
{
for (unsigned j = 0; j < tVector.size(); j++)
{
if (j <= tMatrix.size2())
tMatrix(i, j) = tVector[j];
else
tMatrix(i + 1, j - tMatrix.size2()) = tVector[j];
}
}
// Following is just to populate it randomly
std::random_shuffle(tMatrix.begin1(), tMatrix.end1());
std::random_shuffle(tMatrix.begin2(), tMatrix.end2());
}
}
}
快速主试一下:
int main()
{
std::vector< int > ciao;
for (int i = 0; i < 12; i++)
ciao.push_back(i);
boost::numeric::ublas::matrix< int > peppa(10, 10);
PopulateGrid< int >(ciao, peppa); // crashes!
/* Check failed in file C:\DevTools\boost_1_54_0/boost/numeric/ublas/functional.hpp
* at line 1371:
* j < size_j
* terminate called after throwing an instance of 'boost::numeric::ublas::bad_index'
* what(): bad index
*/
return 0;
}
重点是:我错过了一些更简单的索引操作来获得相同的结果,而且我正在弄乱索引。
我会完全重写这个答案,现在它更多的是一个答案而不是一个建议。
同样,您遇到的问题是:
for (unsigned j = 0; j < tVector.size(); j++) {
if (j <= tMatrix.size2())
tMatrix(i, j) = tVector[j];
else
tMatrix(i + 1, j - tMatrix.size2()) = tVector[j];
}
这是您正在使用的嵌套 for 循环结构的内部循环。在这里,您 运行 遍历整个向量。当 j 超过 size2 时,您不会退出循环,而是将 (i+1) 作为 tMatrix(i1,i2) 的第一个索引。然后对于 i2,您从 j 中减去 size2。
两个问题:一旦你的 j 超过 size2 你将永远重写到矩阵 i1 索引值 1。
然后,如果 j 变得大于 2*size2,您将尝试写出边界索引。比如vecor包含20个元素,你有一个7*7的矩阵,你会在vectorIndex一变成8就写vectorIndex-7。【注意你的<=tMatrix.size2()也是错误的,应该是only < ).这一直有效,直到 vectorIndex 为 14 或更大,因为 14-7 = 7 或 great -> out of bound.
第二个问题是您的外部 for 循环仍将进行迭代并为每个 i 值调用整个过程。最后,您将达到允许的最大 i 值,并且在您的内部循环中,您将尝试访问 (i+1)。这也会给你一个超出范围的期望。
我会建议这样的解决方案:
for ( std::vector<T>::iterator it = yourVector.begin(), int rowIndex = 0, colmIndex = 0;
it != yourVector.end(); ++it, colmIndex++ ) {
if ( colmIndex >= yourMatrix.size2() ) {
rowIndex++;
colmIndex = 0;
yourMatrix (rowIndex, colmIndex ) = *it;
}
else {
yourMatrix (rowIndex, colmIndex ) = *it;
}
}
这是未经测试的,按列填充向量。您应该能够自己弄清楚为 byRow 做什么!
让你有一个包含 n
元素的 std::vector< T >
(T
我的意思是任何 class 或类型名称)并且你想要填充一个类似矩阵的对象,例如 class boost::numeric::ublas::matrix< T >
的对象,其维度为 m1
行和 m2
列,逐行或逐列逐个插入这些元素。
首先,它必须是 n <= m1 * m2
或者我们试图用 11 个或更多元素填充,比方说,10 个槽位;然后:如果n <= m1
(分别为n <= m2
)循环就足够了。
但是如果 n > m1
(n > m2
) 你必须拆分你的 std::vector< T >
以避免糟糕的索引问题并根据你的选择填充你的矩阵。
这是我的尝试:
#include <algorithm>
#include <boost/numeric/ublas/matrix.hpp>
#include <vector>
template < class T > inline void PopulateGrid(const std::vector< T >& tVector,
boost::numeric::ublas::matrix< T >& tMatrix,
char by = 'n')
{
if (tVector.size() > tMatrix.size1() * tMatrix.size2())
throw("Matrix is too small to contain all the array elements!");
else
{
switch(by)
{
case 'r' :
for (unsigned i = 0; i < tMatrix.size1(); i++)
{
for (unsigned j = 0; j < tVector.size(); j++)
{
if (j <= tMatrix.size2())
tMatrix(i, j) = tVector[j];
else
tMatrix(i + 1, j - tMatrix.size2()) = tVector[j];
}
}
break;
case 'c' :
for (unsigned j = 0; j < tMatrix.size2(); j++)
{
for (unsigned i = 0; i < tVector.size(); i++)
{
if (i <= tMatrix.size1())
tMatrix(i, j) = tVector[i];
else
tMatrix(i - tMatrix.size1(), j + 1) = tVector[j];
}
}
break;
default:
for (unsigned i = 0; i < tMatrix.size1(); i++)
{
for (unsigned j = 0; j < tVector.size(); j++)
{
if (j <= tMatrix.size2())
tMatrix(i, j) = tVector[j];
else
tMatrix(i + 1, j - tMatrix.size2()) = tVector[j];
}
}
// Following is just to populate it randomly
std::random_shuffle(tMatrix.begin1(), tMatrix.end1());
std::random_shuffle(tMatrix.begin2(), tMatrix.end2());
}
}
}
快速主试一下:
int main()
{
std::vector< int > ciao;
for (int i = 0; i < 12; i++)
ciao.push_back(i);
boost::numeric::ublas::matrix< int > peppa(10, 10);
PopulateGrid< int >(ciao, peppa); // crashes!
/* Check failed in file C:\DevTools\boost_1_54_0/boost/numeric/ublas/functional.hpp
* at line 1371:
* j < size_j
* terminate called after throwing an instance of 'boost::numeric::ublas::bad_index'
* what(): bad index
*/
return 0;
}
重点是:我错过了一些更简单的索引操作来获得相同的结果,而且我正在弄乱索引。
我会完全重写这个答案,现在它更多的是一个答案而不是一个建议。
同样,您遇到的问题是:
for (unsigned j = 0; j < tVector.size(); j++) {
if (j <= tMatrix.size2())
tMatrix(i, j) = tVector[j];
else
tMatrix(i + 1, j - tMatrix.size2()) = tVector[j];
}
这是您正在使用的嵌套 for 循环结构的内部循环。在这里,您 运行 遍历整个向量。当 j 超过 size2 时,您不会退出循环,而是将 (i+1) 作为 tMatrix(i1,i2) 的第一个索引。然后对于 i2,您从 j 中减去 size2。
两个问题:一旦你的 j 超过 size2 你将永远重写到矩阵 i1 索引值 1。 然后,如果 j 变得大于 2*size2,您将尝试写出边界索引。比如vecor包含20个元素,你有一个7*7的矩阵,你会在vectorIndex一变成8就写vectorIndex-7。【注意你的<=tMatrix.size2()也是错误的,应该是only < ).这一直有效,直到 vectorIndex 为 14 或更大,因为 14-7 = 7 或 great -> out of bound.
第二个问题是您的外部 for 循环仍将进行迭代并为每个 i 值调用整个过程。最后,您将达到允许的最大 i 值,并且在您的内部循环中,您将尝试访问 (i+1)。这也会给你一个超出范围的期望。
我会建议这样的解决方案:
for ( std::vector<T>::iterator it = yourVector.begin(), int rowIndex = 0, colmIndex = 0;
it != yourVector.end(); ++it, colmIndex++ ) {
if ( colmIndex >= yourMatrix.size2() ) {
rowIndex++;
colmIndex = 0;
yourMatrix (rowIndex, colmIndex ) = *it;
}
else {
yourMatrix (rowIndex, colmIndex ) = *it;
}
}
这是未经测试的,按列填充向量。您应该能够自己弄清楚为 byRow 做什么!