Frage an c++ – Berechnung des Skalarprodukts zweier Vektoren in C ++

13

Ich versuche ein Programm mit einer Funktion zu schreibendouble_product(vector<double> a, vector<double> b) das berechnet das Skalarprodukt von zwei Vektoren. Das Skalarprodukt ist

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

Hier ist was ich habe. Es ist ein Durcheinander, aber ich versuche es!

#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;
}
@ HowardRoark Ich habe jetzt die Frage. Was passiert, wenn Sie es ausführen? Stehen Sie vor einem Fehler oder erhalten Sie die falsche Antwort für einen Beispielfall? Ankit
Ich möchte euch alle dafür sprechen, dass ihr mir geholfen habt! Ihr Jungs seid toll! HowardRoark
@Ankit, wenn ich es laufen lasse, kompiliert es nicht. Mein Code ist völlig durcheinander. :( HowardRoark
@ HowardRoark ja, es wird nicht kompiliert. Ich sehe dort zu viele Fehler. Ich werde den korrigierten Code bald veröffentlichen. Mach dir keine Sorgen :) Ankit

Deine Antwort

5   die antwort
40

Sofern Sie dies nicht selbst tun müssen (z. B. das Schreiben von Hausaufgaben), sollten Sie den Standardalgorithmus verwenden, der bereits geschrieben wurde, um genau das zu tun, was Sie möchten:

#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;
}

Beachten Sie, dass währendbegin(a) undend(a) sind neu in C ++ 11,std::inner_product ist seit C ++ 98 verfügbar. Wenn Sie C ++ 98 (oder 03) verwenden, ist es ziemlich einfach, ein eigenes Äquivalent von zu schreibenbegin undend um mit Arrays zu arbeiten:

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;
}

Mit diesen könnte eine C ++ 98-Version des vorherigen Codes ungefähr so ​​aussehen:

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;
}

Notiere dass derbegin undend oben wird nur für Arrays funktionieren, bei denen diebegin undend in C ++ 11 (und höher) funktioniert auch für normale Auflistungstypen, die eine.begin() und.end() (obwohl es trivial ist, Überladungen hinzuzufügen, um diese natürlich auch zu handhaben):

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

Sie können das löschenclass Sie haben definiert. Du brauchst es nicht.

In deinerscalar_product Funktion:

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;
}

Es ist fast da. Sie brauchen keine 2 Schleifen. Nur einer.

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;
}

Jetzt zuAnruf Für diese Funktion müssen Sie 2 Vektorobjekte in Ihrer erstellenmain(), füllen Sie sie mit Werten (natürlich die gleiche Anzahl von Werten!) und rufen Sie dann aufscalar_product( first_vector_that_you_create, second_vector_object );

Die Fehlerbehandlung in dieser Implementierung ist gefährlich. -1 steht im Skalarprodukt nicht für undefiniert. Das kann manchmal sehr gut vorkommen. Dort wird eine Warnung ausgedruckt, die jedoch leicht ignoriert werden kann, insbesondere bei großen Programmen, bei denen die Textausgabe ausgeblendet sein kann oder bei denen viel gedruckter Text vorhanden ist. Versuchen Sie es stattdessennumeric_limits <double> :: quiet_NaN (); Welche Rückkehr nan. patrik
Die Verfolgung einer NaN, die nicht das Ergebnis einer Teilungsoperation war, dürfte doppelt schwierig sein. bobobobo
Nun, es wäre viel gefährlicher, einen Wert hinzuzufügen, der bei einer korrekten Operation auftreten kann. Dann wissen Sie möglicherweise nicht einmal, dass es dort einen Fehler gibt. Wenn Sie jedoch eine Zahl hinzufügen, die nicht wie nan zulässig ist, kann dies später einen Fehler oder eine Ausnahme verursachen, die den Benutzer darauf hinweist, dass etwas nicht stimmt. Das Hinzufügen eines ASSERT ist jedoch wahrscheinlich besser, +1 patrik
Ich würdenoch nieimmer, immer, freiwilligNaN einführen in mein Programm. NaN ist giftig (NaN * -Zahl = NaN, NaN + -Zahl = NaN), sodass es sich im gesamten Programm ausbreitet und herausfindetwoher Die NaN-Produktion ist tatsächlich schwierig (es sei denn, Ihr Debugger kann bei der NaN-Produktion sofort abstürzen). Das heißt, ein mysteriöses -1 ist möglicherweise nicht einfach als mysteriöse 0 zu verfolgen, daher kann ich dieses -1 in eine 0 ändern. Wenn Sie die Textausgabe Ihres Programms nicht regelmäßig überwachen, würde ich wahrscheinlich auch einen ASSERT hinzufügen in diesen Zustand. Abernoch nie NaN zurückgeben. bobobobo
0

Sie scheinen eine Klasse speziell für Vektoren erstellen zu wollen. Die Klasse, die ich in meinem Beispiel erstellt habe, ist auf dreidimensionale Vektoren zugeschnitten, aber Sie können sie bei Bedarf in eine andere ändern. Die Klasse enthält i, j, k, kann aber auch Skalarprodukte basierend auf anderen MathVectors ausführen. Der andere Vektor wird über eine C ++ - Referenz übergeben. Es ist schwer abzuleiten, was die Frage war, aber ich denke, das könnte sie beantworten.

#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;
}
3

Ich habe Ihnen bereits viele Lösungen vorgestellt, die funktionieren. Lassen Sie mich jedoch eine andere Variante vorstellen, um einige Konzepte vorzustellen, die Ihnen helfen sollen, besseren Code zu schreiben:

class werden nur zum Zusammenpacken von Daten benötigtEine Funktion sollte ihre Voraussetzungen so schnell wie möglich prüfen, diese sollten dokumentiert werdenEine Funktion sollte Nachbedingungen haben, diese sollten dokumentiert seinDie Wiederverwendung von Code ist der Grundstein für wartungsfähige Programme

In diesem Sinne:

// 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

Sie könnten sich dafür entscheiden, das zu verwendeninner_product Algorithmus direkt, aber seien wir ehrlich:

Es sind vier Argumente erforderlich, nicht zweiEs wird nicht überprüft, ob die Argumente dieselbe Größe haben

Also ist es besser, es einzuwickeln.

Hinweis: Ich habe verwendetconst& um dem Compiler anzuzeigen, die Vektoren nicht zu kopieren.

1

Hier ist der Code, den Sie haben sollten. Ich sehe, Sie haben Klasse in Ihrem Code verwendet, den Sie hier nicht wirklich brauchen. Lassen Sie mich wissen, ob die Frage erfordert, dass Sie Klasse verwenden.

Da du neu bist und dieser Code dich erschrecken könnte. Also werde ich versuchen, dies zu erklären, wenn ich gehe. Suchen Sie nach Kommentaren im Code, um zu verstehen, was gerade getan wird, und fragen Sie, ob Sie dies nicht verstehen.

//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;
}

Wenn Sie eine IDE verwenden, müssen Sie sie nur kompilieren und ausführen. Wenn Sie die Befehlszeile auf einem Unix-basierten System mit einem g ++ - Compiler verwenden, tun Sie Folgendes (wobei Scalar.cpp die Datei ist, die Code enthält):

g++ Scalar.cpp -o scalar

Um es auszuführen, tippe einfach

./scalar

Du solltest bekommen1.99 als Ausgabe des obigen Programms.

Verwandte Fragen