向量数组,计算点积

Posted

技术标签:

【中文标题】向量数组,计算点积【英文标题】: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 演示coliru.stacked-crooked.com/view?id=e39d16816d6b7410 我可以看到一个错误 if(a[i]=!0) 那是什么 【参考方案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 元素)

【讨论】:

完美答案..如果仍然找到标志-1的OP可以使用coliru.stacked-crooked.com/view?id=2586943d91c247af并回答50 简化示例代码以提高可读性,删除 -1 元素 /cc @HariomSingh 地图的使用;正是结构的使用方式 @HariomSingh 当然,为了易读性,我采取了一些捷径。您可能更喜欢:coliru.stacked-crooked.com/a/1849ef636aa53a93 将稀疏向量视为const - 并且由于基于节点的容器std::map 而不会浪费空间【参考方案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;

【讨论】:

以上是关于向量数组,计算点积的主要内容,如果未能解决你的问题,请参考以下文章

启发式选择使点积最大化的五列数组

计算机图形学-向量向量加减法向量的点积(乘)向量的叉积(乘)

向量点积计算

09:向量点积计算

线性代数的本质-07-点积与对偶性

AC日记——向量点积计算 openjudge 1.6 09