Ciao Voglio (moltiplicare, aggiungere, ecc.) Vettore per valore scalare per esempio myv1 * 3
, so che posso eseguire una funzione con un forloop, ma c'è un modo per farlo usando la funzione STL? Qualcosa come la funzione {Algorithm.h: transform}?Moltiplicare elementi vettoriali con un valore scalare usando STL
risposta
Sì, utilizzando std::transform
:
std::transform(myv1.begin(), myv1.end(), myv1.begin(),
std::bind1st(std::multiplies<T>(),3));
Se è possibile utilizzare uno valarray
anziché uno vector
, ha incorporato gli operatori per eseguire una moltiplicazione scalare.
v *= 3;
Se si deve usare un vector
, è possibile infatti utilizzare transform
per fare il lavoro:
transform(v.begin(), v.end(), v.begin(), _1 * 3);
(ammesso che abbiate qualcosa di simile a Boost.Lambda che permette di creare facilmente oggetti funzione anonimi come _1 * 3
:-P)
Valarray sono la soluzione corretta IMO. Con un po 'di fortuna, la tua implementazione utilizza le istruzioni SSE per implementare la procedura, rendendola notevolmente più veloce. Vedi http://www.pixelglow.com/macstl/valarray/ per una tale implementazione di valarray. Sfortunatamente, non è molto diffuso, quindi se vuoi i vantaggi delle istruzioni SSE probabilmente dovrai usare le intrinseche del compilatore ... – Dragontamer5788
@Dragon: 'valarray' è la migliore soluzione STL, ma non è molto buona per le alte prestazioni calcolo perché tende a copiare molti dati in memoria e produce sequenze di piccoli loop contenenti singole operazioni che hanno schemi di accesso alla memoria scadenti. Tuttavia, è più semplice eseguire l'aggiornamento da 'valarray' a un sistema di modelli di espressioni corretto. – Potatoswatter
Giusto: se è possibile avere i dati in una matrice di dimensioni fisse (valori float [N]), è possibile utilizzare le proprietà intrinseche di SSE per renderle più rapide, in quanto moltiplicherà il numero di volte per volta (4).
So che questo non è STL come si desidera, ma è qualcosa che è possibile adattare in base alle diverse esigenze.
Di seguito è riportato un modello che è possibile utilizzare per calcolare; 'func' sarebbe la funzione che vuoi fare: moltiplicare, aggiungere e così via; 'parm' è il secondo parametro del 'func'. Puoi facilmente estenderlo per prendere diverse funzioni con più parme di tipi diversi.
template<typename _ITStart, typename _ITEnd, typename _Func , typename _Value >
_ITStart xform(_ITStart its, _ITEnd ite, _Func func, _Value parm)
{
while (its != ite) { *its = func(*its, parm); its++; }
return its;
}
...
int mul(int a, int b) { return a*b; }
vector<int> v;
xform(v.begin(), v.end(), mul, 3); /* will multiply each element of v by 3 */
Inoltre, questa non è una funzione di 'sicuro', è necessario eseguire il tipo/valore-checking ecc prima di usarla.
Funziona, ma essenzialmente reinventa la ruota, poiché 'std :: transform' lo fa già per te. –
Sì - ho visto nella risposta accettata ... ma ti rendi conto di quale piacere sia reinventare una ruota che funzioni effettivamente;) Comunque mi sparerò il giorno in cui diventerò un conformista;) – slashmais
Credo for_each
è molto apt quando si vuole attraversare un vettore e manipolare ogni elemento secondo alcuni modello, in questo caso un semplice lambda sarebbe sufficiente:
std::for_each(myv1.begin(), mtv1.end(), [](int &el){el *= 3; });
nota che ogni variabile che si desidera catturare per la funzione lambda da utilizzare (ad esempio, per esempio, si desidera moltiplicare con un determinato scalare predeterminato), entra nella parentesi come riferimento.
Questo non è lo scopo di ' std :: for_each'. 'std :: for_each' applica alcuni oggetti funzione (probabilmente stateful) a un intervallo e quindi restituisce questo oggetto funzione. Se vuoi trasformare un intervallo usa 'std :: transform' per rendere più chiaro il tuo intento. – sv90
Grazie mille questo è genio !! –