2012-01-16 8 views
5

Básicamente para cosas como esta (no código real):¿Es seguro multiplicar un flotante/doble por 0.5 en lugar de dividir por 2 en C# y C++?

for(int i = 0; i < 1000000000; ++i) 
{ 
    Vert v0 = mesh.polygons[i].edges[0].vert0; 
    Vert v1 = mesh.polygons[i].edges[0].vert1; 

    Vector3 center = (v0.pos + v1.pos)/2; 
} 

v0.pos es de tipo Vector3<float, float, float>, pero podría ser Vector3<double, double, double>.

¿Es seguro acaba de hacer ?:

Vector3 center = (v0.pos + v1.pos) * 0.5; 

Esto podría parecer como la optimización prematura, pero esto tiene que ser lo más rápido posible que se pidió a los mil millones de puntos (nube de puntos).

+6

¿Qué sucede cuando se mide el rendimiento de ambas opciones? No puede hablar de optimización en este nivel sin * medir * el resultado en su plataforma objetivo. –

+0

Mídalo de cualquier manera. Pero su compilador 'debería' ya revertir a cambio de bit para dividir por 2. – CaffGeek

+1

De acuerdo con Greg. Además, tenga en cuenta que debe centrarse en la corrección antes de la velocidad.La mayoría de las veces, el compilador optimizará gran parte de esto para usted (especialmente cuando usa literales). – TheBuzzSaw

Respuesta

3

No es un C++ experto, por cualquier medio, pero en C#, hacer esto:

var a = new Func<float, float, double>((float f1, float f2) => (f1 + f2) * 0.5); 
var b = new Func<float, float, double>((float f1, float f2) => (f1 + f2)/2); 

genera IL que en los anteriores:

  1. Carga los argumentos
  2. los añade (produciendo una single)
  3. Convierte el resultado en un doble
  4. Carga el doble argumento (0.5)
  5. Multiplica (produciendo un doble)
  6. devuelve el resultado

y el segundo

  1. Carga los argumentos
  2. los añade (produciendo un solo)
  3. Carga el número entero constante (2)
  4. Divide (produciendo una sola, porque single/integer produce una sola)
  5. convierte el resultado a un doble
  6. devuelve el resultado

se me ocurre que el primero será probable es que tenga una mayor precisión debido a la multiplicación se realiza en 2 dobles, lo que resulta en doble precisión, mientras que en el segundo el la división se realiza en un solo que se eleva a la doble (pero aún así solo tendrá la precisión del sencillo).

Esto me lleva a cabo:

Console.Out.WriteLine(((double)1) * ((double)1/3)); 
Console.Out.WriteLine((1)/((float)3)); 

produce:

0.333333333333333 
0.3333333 

Así, 'seguro', tal vez, si perder precisiónganando precisión adicional es aceptable.

+0

*" 5. Convierte el resultado en un doble "*: ¿Están esos delegados' Func 'por casualidad? – Groo

+0

Sí, lo siento, mala copia de mi parte ... Reparado. –

+0

Verdadero y buen punto, pero me parece que la pregunta es si cambiar la división a una multiplicación podría cambiar el resultado (asumiendo la misma entrada para ambos), en cuyo caso no veo cómo sería esta la caso. es decir, fundición (f1 + f2) para duplicar antes de dividir o 0.5 para flotar y el resultado debería ser idéntico – Voo

Cuestiones relacionadas