【问题标题】:Vector arrays, calculation dot product向量数组,计算点积
【发布时间】:2017-09-18 14:56:45
【问题描述】:

我正在尝试编写计算两个给定向量的点积的 C++ 程序。在向量 a 和 b 中,只有非零元素将存储到结构数组中。每次我得到不相关的结果。正确的结果是 50。我认为我无法将向量正确读取到结构数组中。请指教。提前谢谢你

#include <iostream>
#include <vector>
using namespace std;

const int n=10; /* vector size limit */
struct element {
int x; /* original index of non-zero array element */
int val ; /* integer non-zero value at index x */
};
element row[n];
element col[n];

int i;
vector<int> a={0,0,7,0,5,0,0,8,0,4,-1};
vector<int> b={0,0,0,5,6,0,0,0,0,5,-1};

void generate_row_and_col()
 {
    for (i=0; i<=n; i++)
    {
        if(a[i]=!0)
        {
            row[i].x=i;
            row[i].val=a[i];
        }
    }
    for (i=0; i<=n; i++)
    {
        if(b[i]!=0)
        {
           col[i].x=i;
           col[i].val=b[i];
        }
    }
}
int dotproduct()
{
/* calculate the dot product of row and col output the result*/
int i=0;
int j=0;
int product=0;
while(row[i].x!=-1 && col[j].x!=-1)
{
    if(row[i].x == col[j].x)
    {
        product=product+row[i].val*col[j].val;
        i++;
        j++;
    }
    else if(row[i].x<col[j].x)
    {
        i++;
    }
    else
    {
        j++;
    }
}
return product;
}
int main()
{
generate_row_and_col() ;
int r;
r=dotproduct();
cout<<"result="<<r<<endl;
return 0;
}

【问题讨论】:

  • 你的结果应该是 51 而不是 50
  • for (i=0; i&lt;=n; i++) 在 C++ 数组索引中从 0...n-1 开始,其中 n = 数组长度。
  • 5*6+4*5+-1*-1 = 51
  • 我可以看到一个错误 if(a[i]=!0) 那是什么

标签: c++ arrays loops vector structure


【解决方案1】:

标准库有std::inner_product 用于正是这个目的。使用它可以将您的代码简化为以下内容:

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

int main() {
    std::vector<int> a = { 0,0,7,0,5,0,0,8,0,4 };
    std::vector<int> b = { 0,0,0,5,6,0,0,0,0,5 };

    std::cout << std::inner_product(a.begin(), a.end(), b.begin(), 0);
}

【讨论】:

    【解决方案2】:

    使用= !0 是一个错误。那应该是!= 0

    我仍在猜测目标,但也许另一个清理过的版本会有所帮助:

    Live On Coliru

    #include <iostream>
    #include <vector>
    #include <map>
    using namespace std;
    
    using Ints = vector<int>;
    using Vec = map<int, int>;
    Vec row, col;
    
    Vec to_sparse_vec(Ints const& a) {
        Vec v;
        for (size_t i = 0; i < a.size(); ++i) {
            if (a[i] != 0) v[i] = a[i];
        }
        return v;
    }
    
    int dotproduct(Vec row, Vec col) {
        size_t n = max(row.rbegin()->first, col.rbegin()->first);
    
        int product = 0;
        for (size_t i = 0; i <= n; ++i) {
            if (row[i] && col[i])
                product += row[i] * col[i];
        }
        return product;
    }
    
    int main() {
        auto row = to_sparse_vec({ 0, 0, 7, 0, 5, 0, 0, 8, 0, 4 });
        auto col = to_sparse_vec({ 0, 0, 0, 5, 6, 0, 0, 0, 0, 5 });
        cout << "result=" << dotproduct(row, col) << endl;
    }
    

    这假定Vec 表示旨在作为“稀疏向量”。

    结果是 50(删除了 -1 元素)

    【讨论】:

    【解决方案3】:

    你可以简化你的代码

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    template<class InputIt1, class InputIt2, class T>
    T dot_product(InputIt1 first1, InputIt1 last1,
                    InputIt2 first2, T value)
    {
        while ((first1 != last1)&&(*first1!=-1) && (*first2 !=-1)) {
             value = value + *first1 * *first2;
             ++first1;
             ++first2;
        }
        return value;
    }
    
    const int n=10; /* vector size limit */
    struct element {
        int x; /* original index of non-zero array element */
        int val ; /* integer non-zero value at index x */
    };
    element row[n];
    element col[n];
    
    int i;
    vector<int> a={0,0,7,0,5,0,0,8,0,4,-1};
    vector<int> b={0,0,0,5,6,0,0,0,0,5,-1};
    
    int main()
    {
        int r;
        r=dot_product(a.begin(), a.end(), b.begin(), 0);
        cout<<"result="<<r<<endl;
        return 0;
    }
    

    输出

    50

    Demo

    【讨论】:

    • 那是不正确的结果。进一步简化:coliru.stacked-crooked.com/a/bc586f3a890ceab0 正确打印 51
    • @sehe 完美只添加了一个。他只想要正值,因此可以为负添加条件标志
    • 我不确定我明白了,但无论如何。我希望OP实现他的目标
    • @sehe 我第一次看到库 valarray ..那是什么?
    • 我个人不知道,因为我不知道你打算做什么。 generate_row_and_col 的所有混乱,单独的 i++j++ - 这对我来说都是魔法。规则一:代码是为人类设计的。意图表达优先于其他任何事情。
    【解决方案4】:

    我已经对代码进行了一些更改,现在可以正常工作了。但是,在 generate_row_and_col 函数上初始化 row 和 col 数组时,我只用非零元素初始化索引,其余的没有初始化。这不会导致该程序出现任何错误,但就良好的编程习惯而言,那些值为 0 的索引不会被初始化,数组看起来像 (garbage,garbage,7,garbage,5,garbage,garbage.... )。我们可以只限制 generate_row_and_col 函数,所以我们只能存储非零值索引。 谢谢你

    #include <iostream>
    #include <vector>
    using namespace std;
    
    const int n=11; /* vector size */
    
    struct element {
    int index; /* original index of non-zero array element */
    int value ; /* integer non-zero value at index x */
    };
    element row[n];
    element col[n];
    
    vector<int> a={0,0,7,0,5,0,0,8,0,4,-1};
    vector<int> b={0,0,0,5,6,0,0,0,0,5,-1};
    
    void generate_row_and_col()
    {
        for (int i=0; i<n; i++)
        {
            if(a[i]!=0)
            {
                row[i].index=i;
                row[i].value=a[i];
            }
        }
        for (int j=0; j<n; j++)
        {
            if(b[j]!=0)
            {
               col[j].index=j;
               col[j].value=b[j];
            }
        }
    }
    int dotproduct()
    {
    /* calculate the dot product of row and col output the result*/
    int i=0;
    int j=0;
    int product=0;
    while(row[i].value!=-1 && col[j].value!=-1)
    {
        if(row[i].index == col[j].index)
        {
            product=product+row[i].value*col[j].value;
            i++;
            j++;
        }
        else if(row[i].index<col[j].index)
        {
            i++;
        }
        else
        {
            j++;
        }
    }
    return product;
    }
    
    int main()
    {
        generate_row_and_col() ;
        int r;
        r=dotproduct();
        cout<<"Dot Product = "<<r<<endl;
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-04
      • 2015-08-06
      • 2021-07-11
      • 2016-05-07
      • 2010-09-19
      • 2021-01-23
      • 1970-01-01
      相关资源
      最近更新 更多