2012-06-06 59 views
7

Sto provando a scrivere un programma con una funzione double_product(vector<double> a, vector<double> b) che calcola il prodotto scalare di due vettori. Il prodotto scalare èCalcolo del prodotto scalare di due vettori in C++

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

Ecco quello che ho. È un casino, ma ci sto provando!

#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

C'è davvero una domanda qui? –

+0

Che cos'è "bouble"? – jakebird451

+0

La tua domanda non è molto chiara. Abbiamo capito che sono i tuoi compiti. Ma quale domanda stai cercando di risolvere e aggiungere un piccolo dettaglio su quale problema stai affrontando? – Ankit

risposta

10

È possibile eliminare lo class definito. Non ne hai bisogno.

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

è quasi lì. Non hai bisogno di 2 loop. Solo uno.

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

Ora per chiamata questa funzione, è necessario creare 2 oggetti vettoriali nella vostra main(), riempirli con valori, (lo stesso numero di valori ovviamente!) E quindi chiamare scalar_product(first_vector_that_you_create, second_vector_object);

+1

La gestione degli errori in questa implementazione è pericolosa. -1 non sta per non definito nel prodotto scalare. Questo può apparire molto bene a volte. C'è un avviso stampato là fuori, ma questo può essere facilmente ignorato, in particolare per i programmi di grandi dimensioni in cui il testo dell'output del testo può essere nascosto, o se c'è un sacco di testo stampato. Prova invece * numeric_limits :: quiet_NaN(); * Che restituisce nan. – patrik

+1

Non vorrei, mai, mai, volontariamente [introdurre NaN] (http://stackoverflow.com/a/18283170/111307) nel mio programma. Il NaN è tossico (NaN * numero = NaN, NaN + numero = NaN), quindi si propaga nel tuo programma, e capire dove il NaN è stato prodotto è effettivamente difficile (a meno che il tuo debugger non si rompa immediatamente sulla produzione NaN). Detto questo, un misterioso -1 potrebbe non essere facile da tracciare come un misterioso 0, quindi potrei cambiarlo da -1 a 0. Se non controlli regolarmente l'output testuale del tuo programma, probabilmente aggiungerei anche un ASSERT in quella condizione. Ma __never__ restituisce NaN. – bobobobo

+0

Tenere traccia di un NaN che non era il risultato di un'operazione di divisione mi aspetterei di essere doppiamente difficile. – bobobobo

0

È sembra voler fare una lezione specifica per i vettori. La classe che ho creato nel mio esempio è personalizzata per i vettori tridimensionali, ma è possibile modificarla in un altro se lo si desidera. La classe contiene i, j, k ma può anche gestire prodotti scalari basati su altri MathVector. L'altro vettore è passato attraverso un riferimento C++. È difficile dedurre quale fosse la domanda, ma penso che questo potrebbe rispondere.

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

Ecco il codice che si dovrebbe avere. Vedo che hai usato la classe nel tuo codice, di cui non hai davvero bisogno qui. Fammi sapere se la domanda richiedesse di usare la lezione.

Come sei nuovo e questo codice potrebbe spaventarti. Quindi, cercherò di spiegarlo mentre vado. Cerca i commenti nel codice per capire cosa si sta facendo e chiedi se non capisci.

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

Se si utilizza un IDE, è sufficiente compilare ed eseguire. Se si utilizza da riga di comando su un sistema Unix-based con il compilatore g ++, questo è ciò che si fa (dove Scalar.cpp è il file di codice che contiene):

g++ Scalar.cpp -o scalar 

per eseguirlo è sufficiente digitare

./scalar 

Si dovrebbe ottenere 1.99 come output del programma di cui sopra.

+0

Grazie, apprezzo il tuo aiuto: D – HowardRoark

33

A meno che non è necessario fare da soli (ad esempio, la scrittura è compiti a casa), si dovrebbe davvero utilizzare l'algoritmo standard che è già scritto per fare esattamente quello che vuoi:

#include <iostream> 
#include <numeric> 

int main() { 
    double a[] = {1, 2, 3}; 
    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; 
} 

notare che, mentre il begin(a), end(a) è nuovo in C++ 11, std::inner_product disponibile dal C++ 98.

+8

+1 per avermi insegnato su inner_product'. –

3

Mentre v'è stato presentato molte soluzioni che funzionano, mi permetta di spin up un'altra variazione di introdurre un paio di concetti che dovrebbero aiutare a scrivere codice migliore:

  • class solo sono necessari per il confezionamento dei dati insieme
  • una funzione dovrebbe controllare le sue condizioni appena possibile, quelli dovrebbe essere documentata
  • funzione dovrebbe avere postcondizioni, quelli devono essere documentate
  • riutilizzo del codice è la chiave di programmi maintenable

Con questo in mente:

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

Si potrebbe decidere di utilizzare la inner_product algoritmo direttamente, ma ammettiamolo:

  • Richiede quattro argomenti, non due
  • lo fa non verificare se i suoi argomenti sono della stessa dimensione

quindi è meglio avvolgerlo.

Nota: ho utilizzato const& per indicare al compilatore di non copiare i vettori.

+0

Grazie! Lo apprezzo molto. – HowardRoark