在C++中计算两个向量的数量积

18

我正在尝试编写一个带有函数double_product(vector<double> a, vector<double> b)的程序,该函数计算两个向量的数量积。数量积是

$a_{0}b_{0}+a_{1}b_{1}+...+a_{n-1}b_{n-1}$.

这是我的代码,虽然有些杂乱无章,但我正在努力!

#include <iostream>
#include <vector>

using namespace std;

class Scalar_product
{
    public:
    Scalar_product(vector<double> a, vector<double> b);
};
double scalar_product(vector<double> a, vector<double> b)
{
    double product = 0;
    for (int i = 0; i <= a.size()-1; i++)
        for (int i = 0; i <= b.size()-1; i++)
            product = product + (a[i])*(b[i]);
    return product;
}

int main() {
    cout << product << endl;
    return 0;
}

1
这里实际上有一个问题吗? - Michael Anderson
@HowardRoark 我明白问题了。当你运行它时会发生什么?你遇到了一些错误或者某些示例情况下得到了错误的答案吗? - Ankit
@Ankit 当我运行它时,它无法编译。我的代码全乱了。 :( - HowardRoark
@HowardRoark 是的,它无法编译。我在那里看到了太多的错误。我很快会发布更正后的代码。不用担心 :) - Ankit
@Ankit 是的,我是C++的新手,但我正在努力学习。我刚开始学习它。这与数学完全不同。哈哈。谢谢!我真的很感激! - HowardRoark
显示剩余8条评论
5个回答

46

除非你需要自己完成这项任务(例如,这是你的作业),否则你应该使用已经编写好能够完全满足你需求的标准算法:

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

int main() {
    std::vector<double> a {1, 2, 3};
    std::vector<double> b {4, 5, 6};

    std::cout << "The scalar product is: "
              << std::inner_product(std::begin(a), std::end(a), std::begin(b), 0.0);
    return 0;
}

请注意,虽然在C++11中新增了begin(a)end(a)函数,但自C++98以来就已经有std::inner_product函数可用。如果您正在使用C++ 98(或03),编写自己的beginend函数来处理数组也很容易:
template <class T, size_t N>
T *begin(T (&array)[N]) {
    return array;
}

template <class T, size_t N>
T *end(T (&array)[N]) {
    return array + N;
}

使用这些方法,先前代码的C++ 98版本可能如下所示:
int main() {
    double a[] = {1, 2, 3};
    double b[] = {4, 5, 6};

    std::cout << "The scalar product is: "
              << std::inner_product(begin(a), end(a), begin(b), 0.0);
    return 0;
}

注意,上面的 beginend 只适用于数组,在 C++11(及更高版本)中的 beginend 也适用于定义了 .begin().end() 的普通集合类型(当然,添加处理这些类型的重载也是微不足道的):
template <class Coll>
typename Coll::iterator begin(Coll const& c) { return c.begin(); }

template <class Coll>
typename Coll::iterator end(Coll const& c) { return c.end(); }

12
你可以删除你定义的class。它不是必要的。
在你的scalar_product函数中:
double scalar_product(vector<double> a, vector<double> b)
{
    double product = 0;
    for (int i = 0; i <= a.size()-1; i++)
        for (int i = 0; i <= b.size()-1; i++)
            product = product + (a[i])*(b[i]);
    return product;
}

就快搞定了。你不需要两个循环,只需要一个循环。

double scalar_product(vector<double> a, vector<double> b)
{
    if( a.size() != b.size() ) // error check
    {
        puts( "Error a's size not equal to b's size" ) ;
        return -1 ;  // not defined
    }

    // compute
    double product = 0;
    for (int i = 0; i <= a.size()-1; i++)
       product += (a[i])*(b[i]); // += means add to product
    return product;
}

现在要调用这个函数,你需要在main()函数中创建两个向量对象,填充它们的值(当然是相同数量的值!),然后调用scalar_product( first_vector_that_you_create, second_vector_object );


1
这个实现中的错误处理是危险的。-1在标量积中并不代表未定义。有一个警告被打印出来,但这很容易被忽略,特别是对于大型程序,其中文本输出可能被隐藏,或者如果有很多打印文本。尝试使用*numeric_limits<double>::quiet_NaN();*,它会返回nan。 - patrik
1
我绝对不会自愿将NaN引入我的程序中。 NaN是有毒的(NaN*number=NaN,NaN+number=NaN),因此它会在整个程序中传播,并且找出NaN产生的位置实际上很困难(除非您的调试器可以立即在NaN产生时中断)。 也就是说,一个神秘的-1可能不容易追踪为一个神秘的0,所以我可能会将该-1更改为0。 如果您不经常监视程序的文本输出,我可能还会在该条件中添加ASSERT。 但是__永远__不要返回NaN。 - bobobobo
追踪一个不是由除法操作导致的NaN,我会认为这将是双倍困难。 - bobobobo
2
添加一个可能由正确操作产生的值会更加危险。这样,您甚至可能不知道那里存在错误。但是,添加一个不允许的数字(如nan)可能会在以后引发错误或异常,从而让用户知道出现了问题。然而,添加ASSERT可能会更好,+1。 - patrik

3

虽然你已经被呈现出许多可行的解决方案,但是让我提出另一种变化,介绍一些概念,这些概念应该有助于您编写更好的代码:

  • class仅用于将数据打包在一起
  • 函数应尽早检查其前提条件,这些条件应该得到记录
  • 函数应具有后置条件,这些条件应该得到记录
  • 代码重用是可维护程序的基石

记住这些要点:

// Takes two vectors of the same size and computes their scalar product
// Returns a positive value
double scalar_product(std::vector<double> const& a, std::vector<double> const& b)
{
    if (a.size() != b.size()) { throw std::runtime_error("different sizes"); }

    return std::inner_product(a.begin(), a.end(), b.begin(), 0.0);
} // scalar_product

你可以直接使用inner_product算法,但让我们面对现实吧:
  • 它需要四个参数而不是两个
  • 它不会检查其参数是否具有相同的大小
因此最好将其封装起来。 注意:我使用const&指示编译器不要复制向量。

0

你似乎想要创建一个专门用于向量的类。我在示例中创建的类是针对三维向量量身定制的,但如果需要,您可以将其更改为其他向量。该类包含i、j、k,还可以根据其他MathVectors进行标量积。另一个向量通过C++引用传递。很难推断出问题是什么,但我认为这可能会回答它。

#include <iostream>

using namespace std;

class MathVector
{
private:
    double i,j,k;
public:
    MathVector(double i,double j,double k)
    {
        this->i=i;
        this->j=j;
        this->k=k;
    }
    double getI(){return i;}
    double getJ(){return j;}
    double getK(){return k;}
    double scalar(MathVector &other)
    {
        return (i*other.getI())+(j*other.getJ())+(k*other.getK());
    }
};

int main(int argc, char **argv)
{
    MathVector a(1,2,5), b(2,4,1);

    cout << a.scalar(b) << endl;

    return 0;
}

0

这里是你应该拥有的代码。我看到你在代码中使用了类,但实际上在这里并不需要。如果问题要求你使用类,请告诉我。

由于你是新手,这段代码可能会让你感到害怕。因此,我将尝试在解释时进行说明。查找代码中的注释以了解正在执行的操作,并在不理解时提问。

//Scalar.cpp
#include <stdlib.h>
#include <iostream>
#include <vector>

using namespace std;

/**
This function returns the scalar product of two vectors "a" and "b"
*/
double scalar_product(vector<double> a, vector<double> b)
{
    //In C++, you should declare every variable before you use it. So, you declare product and initialize it to 0.
    double product = 0;
    //Here you check whether the two vectors are of equal size. If they are not then the vectors cannot be multiplied for scalar product.
    if(a.size()!=b.size()){
        cout << "Vectors are not of the same size and hence the scalar product cannot be calculated" << endl;
        return -1;  //Note: This -1 is not the answer, but just a number indicating that the product is not possible. Some pair of vectors might actually have a -1, but in that case you will not see the error above.
    }

    //you loop through the vectors. As bobo also pointed you do not need two loops.
    for (int i = 0; i < a.size(); i++)
    {
        product = product + a[i]*b[i];
    }

    //finally you return the product
    return product;
}


 //This is your main function that will be executed before anything else.
int main() {
    //you declare two vectors "veca" and "vecb" of length 2 each
    vector<double> veca(2);
    vector<double> vecb(2);

    //put some random values into the vectors
    veca[0] = 1.5;
    veca[1] = .7;
    vecb[0] = 1.0;
    vecb[1] = .7;

    //This is important! You called the function you just defined above with the two parameters as "veca" and "vecb". I hope this cout is simple!
    cout << scalar_product(veca,vecb) << endl;
}

如果您正在使用IDE,则只需编译和运行。如果您正在使用基于Unix的系统上的命令行,并且使用g++编译器,则需要执行以下操作(其中Scalar.cpp是包含代码的文件):

g++ Scalar.cpp -o scalar

要运行它,只需输入

./scalar

你应该得到 1.99 作为上述程序的输出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接