¿Qué representa la constante 0.0039215689?

310

Sigo viendo esta ventana emergente constante en varios archivos de encabezado de gráficos

0.0039215689

Parece que tiene algo que ver con el color, tal vez?

Aquí está el primer éxito en Google :

void RDP_G_SETFOGCOLOR(void)
{
    Gfx.FogColor.R = _SHIFTR(w1, 24, 8) * 0.0039215689f;
    Gfx.FogColor.G = _SHIFTR(w1, 16, 8) * 0.0039215689f;
    Gfx.FogColor.B = _SHIFTR(w1, 8, 8) * 0.0039215689f;
    Gfx.FogColor.A = _SHIFTR(w1, 0, 8) * 0.0039215689f;
}

void RDP_G_SETBLENDCOLOR(void)
{
    Gfx.BlendColor.R = _SHIFTR(w1, 24, 8) * 0.0039215689f;
    Gfx.BlendColor.G = _SHIFTR(w1, 16, 8) * 0.0039215689f;
    Gfx.BlendColor.B = _SHIFTR(w1, 8, 8) * 0.0039215689f;
    Gfx.BlendColor.A = _SHIFTR(w1, 0, 8) * 0.0039215689f;

    if(OpenGL.Ext_FragmentProgram && (System.Options & BRDP_COMBINER)) {
        glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, Gfx.BlendColor.R, Gfx.BlendColor.G, Gfx.BlendColor.B, Gfx.BlendColor.A);
    }
}

//...more like this

¿Qué representa este número? ¿Por qué nadie parece declararlo como una constante?

No pude encontrar nada en Google que lo explicara.

Persona especial
fuente
16
¿Hay alguna razón por la cual el código fuente escribiría esto en lugar de (1.f/255)?
MM
53
Mmmm ... si hubiera alguna forma de evitar los números mágicos ...
Paul Draper
12
1/255 == 0.00(3921568627450980)- Parens significa repetición.
jfs
82
Con su próximo número mágico, intente preguntar Wolfram Alpha
AakashM
12
sea ​​cual sea la razón, usar un número mágico sin documentar su propósito es muy desagradable
Isaac Rabinovitch el

Respuestas:

378

0.0039215689es aproximadamente igual a 1/255.

Al ver que esto es OpenGL, el rendimiento es probablemente importante. Por lo tanto, es seguro adivinar que esto se hizo por razones de rendimiento.

Multiplicar por el recíproco es más rápido que dividir repetidamente por 255.


Nota al margen:

Si se está preguntando por qué no se deja esa microoptimización al compilador, es porque es una optimización de punto flotante insegura. En otras palabras:

x / 255  !=  x * (1. / 255)

debido a errores de redondeo de punto flotante.

Por lo tanto, si bien los compiladores modernos pueden ser lo suficientemente inteligentes como para hacer esta optimización, no se les permite hacerlo a menos que se lo indique explícitamente a través de un indicador del compilador.

Relacionado: ¿Por qué GCC no optimiza a * a * a * a * a * a a (a * a * a) * (a * a * a)?

Místico
fuente
10
En realidad no sabía qué era cuando lo vi por primera vez. Pero al ver cómo se usaba, sospeché que era la optimización de multiplicar por recíproco. Así que revisé mi calculadora y, efectivamente, acerté.
Mysticial
55
Hubiera esperado verlo escrito como a = b * (1.0f / 255); los compiladores siguen haciendo plegados constantes, ¿no?
Ilmari Karonen
99
@IlmariKaronen Sí, siguen haciendo plegados constantes. En realidad, se requiere para algunas cosas, como resoluciones de plantillas y demás. Pero lo habría sacado como una constante o una macro. Pero bueno, no todo el código está perfectamente escrito. :)
Mysticial
55
@hippietrail Inicialmente, me preguntaba lo mismo. Pero si usa 256, se escalaría en 0.0 - 0.996lugar del deseado 0.0 - 1.0. ( 0.996 = 255/256donde 255es el número entero de 8 bits más grande)
Mysticial
77
Y, por supuesto, para responder a mi propia pregunta, es porque los otros dos números no pueden representarse como flotadores C estándar. El siguiente flotador por debajo de 0.0039215689 es 0.0039215684.
Daniel Waechter
79

Esta multiplicación por 0.0039215689fconvierte una intensidad de color con valor entero en el rango de 0 a 255 a una intensidad de color con valor real en el rango de 0 a 1.

Como señala Ilmari Karonen, incluso si se trata de una optimización, está bastante mal expresada. Sería mucho más claro multiplicar por (1.0f/255).

David Heffernan
fuente
55
O tal vez mejor, definido como constante?
Johny
99
@Johny Definitivamente definido como una constante. El punto no es un valor mágico.
David Heffernan