2010-10-07 16 views

Respuesta

73

Sí, utilizando std::transform:

std::transform(myv1.begin(), myv1.end(), myv1.begin(), 
       std::bind1st(std::multiplies<T>(),3)); 
+0

¡Muchas gracias, eso es genio! –

21

Si puede usar un valarray en lugar de un vector, tiene operadores integrados para hacer una multiplicación escalar.

v *= 3; 

Si tiene que utilizar un vector, de hecho puede utilizar transform para hacer el trabajo:

transform(v.begin(), v.end(), v.begin(), _1 * 3); 

(suponiendo que tiene algo similar a Boost.Lambda que le permite crear fácilmente objetos función anónima como _1 * 3 :-P)

+1

Valarrays son la solución correcta IMO. Con suerte, su implementación utiliza instrucciones SSE para implementar el procedimiento, lo que lo hace significativamente más rápido. Ver http://www.pixelglow.com/macstl/valarray/ para una de esas implementaciones de valarray. Desafortunadamente, no está muy extendido, así que si quieres las ventajas de las instrucciones SSE, probablemente tengas que usar los intrínsecos del compilador ... – Dragontamer5788

+0

@Dragon: 'valarray' es la mejor solución STL, pero no es muy buena para alto rendimiento informática porque tiende a copiar datos en la memoria mucho, y produce secuencias de pequeños bucles que contienen operaciones individuales que tienen patrones de acceso a la memoria deficientes. Sin embargo, es más fácil actualizar de 'valarray' a un sistema de plantilla de expresión adecuado. – Potatoswatter

0

Justo: si usted puede tener sus datos en una matriz de tamaño fijo (valores float [N]), puede utilizar las características intrínsecas de la ESS para hacerlo más rápido, ya que se multiplicará sevreral flotar una vez (4).

0

Sé que esto no STL como desee, pero es algo que se puede adaptar surgen como necesidades diferentes.

A continuación se muestra una plantilla que puede utilizar para calcular; 'func' sería la función que desea hacer: multiplicar, agregar, y así sucesivamente; 'parm' es el segundo parámetro del 'func'. Puedes extender esto fácilmente para tomar diferentes funciones con más parms de tipos variados.

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

Además, esta no es una función 'segura', debe hacer la comprobación de tipo/valor, etc. antes de usarla.

+0

Esto funciona, pero básicamente es reinventar la rueda, ya que 'std :: transform' ya lo hace por usted. –

+0

Sí - vieron en la respuesta aceptada, pero ... ¿Se da cuenta de lo que es el placer de reinventar la rueda que realmente funciona;) De todos modos voy a disparar a mí mismo el día me convierto en un conformista;) – slashmais

0

Creo for_each es muy adecuada cuando se quiere recorrer un vector y manipular cada elemento de acuerdo con algún patrón, en este caso un lambda sencilla sería suficiente:

std::for_each(myv1.begin(), mtv1.end(), [](int &el){el *= 3; }); 

nota de que cualquier variable que desea capturar para la función lambda a utilizar (digamos que, por ejemplo, quería multiplicar con algún escalar predeterminado), entra en el corchete como referencia.

+0

Este no es el propósito de ' std :: for_each'. 'std :: for_each' aplica un objeto de función (probablemente con estado) a un rango y luego devuelve este objeto de función. Si desea transformar un rango, use 'std :: transform' para que su intención sea más clara. – sv90

Cuestiones relacionadas