向量和索引的内积误差

时间:2016-05-12 14:11:59

标签: c++

我在代码中发现了一个错误,无法搞清楚错误。我通过逐步显示每个变量的输出尝试调试,但我找不到我的错误。这是我拥有的和我想做的事情:

我有一个矩阵A:

0000
0101
1010
1111

我有一个矩阵B:

10000
21000
30100
41100
20010
21010
40110
41110
30001
41001
30101
41101
40011
41011
40111
41111

矩阵B有16行和5个coloumns。矩阵A有4行和4个颜色。现在我声明一个有4行16个coloumns的矩阵C.

我想要做的是计算B中每行的内积与来自A的相应行。对应的我意味着B的第一个颜色定义了我想要乘以的A行。所以B矩阵实际上也有四维向量,第一个元素对应于A的行。可以说B的第一个coloumn是用于选择A行的索引。因为C ++从零开始计数我减去一个为我的索引。这是我的代码:

std::vector< std::vector<int> > C(4, std::vector<int>(16));
std::vector<int> index(4);
std::vector<int> vectorA(4);
std::vector<int> vectorB(4);

for( int y = 0; y < 16; y++)
{

    for(int i=0; i<4; ++i){
    vectorA[i] = A[ B[y][0]-1 ][i];
    }

    for( int x = 1; x < 4; x++)
    {

        vectorB[x -1] = B[y][x];

    }


C[ B[y][0] -1][index[ B[y][0] -1] ] = inner_product(vectorA.begin(), vectorA.end(), vectorB.begin(), 0);

    index[B[y][0]-1] += 1;
}

这导致我的矩阵C:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 
2 2 3 1 2 1 2 2 3 0 0 0 0 0 0 0 

前两行是正确的,但第三行和第四行是假的。 必须采用正确的解决方案(可能除了第3行和第4行的排序外):

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 
4 3 3 2 3 2 3 2 2 0 0 0 0 0 0 0 

我的问题在哪里?请帮助,它让我发疯:(我尝试逐步显示每个变量,但无法找到为什么它是假的。

谢谢和问候。

2 个答案:

答案 0 :(得分:0)

我必须同意其他评论:你的代码有点令人困惑。您应该通过索引真正简化向量的访问。

您应该做的第一件事就是将B的第一列更改为从零开始。 C ++中的所有东西都是从零开始的。采纳它。不要通过减去一个来开始在代码中调整它。 (这不会带来太多简单,但对于您的代码来说是有症状的。)

混淆的另一个原因是你使用B的第一列作为A的索引。这可能是你想要解决的问题的一个含义,但它使事情变得不清楚:B的第一列有一个完全不同的含义,总是以一种对象与其含义分开的方式编码。

对我来说最令人困惑的是,我真的没有得到你想要的东西。内部产品是指产品,对吧?您有2组矢量要计算的点积。这应该产生一组标量,一维矢量而不是二维矩阵。你用这个索引向量做了一些特殊的东西,这使得结果成为一个2D矩阵。但是你还没有解释它背后的目的/系统。为什么需要索引的向量,而不仅仅是标量?

Vector index 是代码中最丑陋/最复杂的部分。如果你不知道自己在做什么,我仍然会猜到你在每次迭代时开始打印出完整的向量索引时会发现出了什么问题,并检查它是否改变了你的方式期望的。

答案 1 :(得分:0)

我不知道OP选择背后的理由是什么,所以我无法正确评论所提供的代码设计,但是我能理解的是,示例输入也存在一些错误。

给出A和B矩阵,A的下部行与B中的对应的内积总是0:

                                     B[1]   { 2,     1, 0, 0, 0 },
row "2" or A[1] is { 0, 1, 0, 1 } <- B[4]   { 2,     0, 0, 1, 0 },
                                     B[5]   { 2,     1, 0, 1, 0 },

成功的行也一样。只有交换时,才能获得预期的输出,所以我在我的代码中做了。

vectorAvectorB以及相应的复制循环并非真正必要,可能是错误输出的原因:

for( int x = 1; x < 4; x++)
{ //            ^^^^^  this should be  <=  to reach the last element
    vectorB[x -1] = B[y][x];
}

我的代码,更新后的输入以及A和B的直接使用是:

#include <iostream>
#include <vector>
#include <numeric>

using vec_t = std::vector<int>;   // I assume a C++11 compliant compiler
using mat_t = std::vector<vec_t>;
using std::cout;

int main() {

    mat_t A{
        { 0, 0, 0, 0 },
        { 1, 0, 1, 0 }, // <-- those lines are swapped
        { 0, 1, 0, 1 }, // <--
        { 1, 1, 1, 1 }
    };
    mat_t B{
        { 1, 0, 0, 0, 0 },
        { 2, 1, 0, 0, 0 },
        { 3, 0, 1, 0, 0 },
        { 4, 1, 1, 0, 0 },
        { 2, 0, 0, 1, 0 },
        { 2, 1, 0, 1, 0 },
        { 4, 0, 1, 1, 0 },
        { 4, 1, 1, 1, 0 },
        { 3, 0, 0, 0, 1 },
        { 4, 1, 0, 0, 1 },
        { 3, 0, 1, 0, 1 },
        { 4, 1, 1, 0, 1 },
        { 4, 0, 0, 1, 1 },
        { 4, 1, 0, 1, 1 },
        { 4, 0, 1, 1, 1 },
        { 4, 1, 1, 1, 1 }
    };

    mat_t C(4, vec_t(16));
    vec_t pos(4);

    for ( int i = 0; i < 16; ++i )
    {
        int row = B[i][0] - 1;
        int col = pos[row];
        int prod = std::inner_product( A[row].begin(), A[row].end(),
                                      ++(B[i].begin()), 0 );
        //                            ^^^ skip the first element
        C[row][col] = prod;
        if ( prod )
            ++pos[row];
    }

    for ( auto & r : C )
    {
        for ( int x : r ) {
            cout << ' ' << x;
        }
        cout << '\n';
    }

    return 0;
}

输出结果为:

 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
 1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
 2 2 3 2 3 2 3 3 4 0 0 0 0 0 0 0

我不知道最后一行的排序是否符合预期,但它模仿了OP代码的逻辑。