Que représente la constante 0,0039215689?

310

Je continue de voir cette constante apparaître dans divers fichiers d'en-tête graphiques

0.0039215689

Cela semble avoir quelque chose à voir avec la couleur peut-être?

Voici le premier hit sur 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

Que représente ce nombre? Pourquoi personne ne semble-t-il le déclarer comme const?

Je n'ai rien trouvé sur Google qui l'explique.

écraser
la source
16
Y a-t-il une raison pour que le code source écrive ceci à la place (1.f/255)?
MM
53
Mmmm ... si seulement il y avait un moyen d'éviter les nombres magiques ....
Paul Draper
12
1/255 == 0.00(3921568627450980)- parens signifie répétition.
jfs
82
Avec votre prochain numéro magique, essayez de demander à Wolfram Alpha
AakashM
12
quelle que soit la raison, utiliser un nombre magique sans documenter son but est très cool
Isaac Rabinovitch

Réponses:

378

0.0039215689est approximativement égal à 1/255.

Étant donné qu'il s'agit d'OpenGL, les performances sont probablement importantes. Il est donc probablement sûr de supposer que cela a été fait pour des raisons de performances.

La multiplication par l'inverse est plus rapide que la division répétée par 255.


Note latérale:

Si vous vous demandez pourquoi une telle micro-optimisation n'est pas laissée au compilateur, c'est parce qu'il s'agit d'une optimisation à virgule flottante non sécurisée. En d'autres termes:

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

en raison d'erreurs d'arrondi en virgule flottante.

Ainsi, alors que les compilateurs modernes peuvent être suffisamment intelligents pour effectuer cette optimisation, ils ne sont pas autorisés à le faire à moins que vous ne le leur disiez explicitement via un indicateur de compilateur.

Connexes: Pourquoi GCC n'optimise-t-il pas * a * a * a * a * a à (a * a * a) * (a * a * a)?

Mysticial
la source
10
En fait, je ne savais pas ce que c'était quand je l'ai vu pour la première fois. Mais vu la façon dont il était utilisé, je soupçonnais que c'était l'optimisation multipliée par réciproque. J'ai donc vérifié dans ma calculatrice et bien sûr - j'ai deviné juste.
Mysticial
55
Je m'attendais à le voir écrit comme a = b * (1.0f / 255); les compilateurs font toujours un pliage constant, n'est-ce pas?
Ilmari Karonen
9
@IlmariKaronen Oui, ils font toujours un pliage constant. C'est en fait nécessaire pour certaines choses comme les résolutions de modèles et autres. Mais je l'aurais juste retiré comme une constante ou une macro. Mais bon, tout le code n'est pas parfaitement écrit. :)
Mysticial
5
@hippietrail Au départ, je me demandais la même chose. Mais si vous utilisez 256, il évoluerait à la 0.0 - 0.996place de celui souhaité 0.0 - 1.0. ( 0.996 = 255/256255est le plus grand entier 8 bits)
Mysticial
7
Et bien sûr, pour répondre à ma propre question, c'est parce que les deux autres nombres ne peuvent pas être représentés comme des flotteurs C standard. Le prochain flotteur en dessous de 0,0039215689 est 0,0039215684.
Daniel Waechter
79

Cette multiplication par 0.0039215689fconvertit une intensité de couleur de valeur entière dans la plage de 0 à 255 en une intensité de couleur de valeur réelle dans la plage de 0 à 1.

Comme le souligne Ilmari Karonen, même s'il s'agit d'une optimisation, elle est plutôt mal exprimée. Il serait tellement plus clair de multiplier par (1.0f/255).

David Heffernan
la source
5
Ou peut-être mieux, défini comme constant?
Johny
9
@Johny Certainement défini comme une constante. Le point n'étant pas une valeur magique.
David Heffernan